History

Merge branch 'git-ref-refactor'

Sebastian Thiel committed 5 years ago

Commit 5dbf7532 parents 09a777f 679895c57 files · +556 −561Browse files

Unified · Split

57 files
  1. Cargo.lock +1 −1
  2. cargo-smart-release/src/command/release/git.rs +2 −5
  3. experiments/diffing/src/main.rs +1 −1
  4. experiments/traversal/src/main.rs +1 −1
  5. git-actor/Cargo.toml +1 −1
  6. git-actor/src/lib.rs +0 −2
  7. git-actor/src/signature/decode.rs +2 −5
  8. git-actor/src/signature/mod.rs +17 −0
  9. git-actor/src/signature_ref/mod.rs +0 −14
  10. git-object/Cargo.toml +1 −1
  11. git-object/src/immutable/parse.rs +1 −1
  12. git-object/src/types.rs +1 −1
  13. git-ref/Cargo.toml +1 −1
  14. git-ref/src/fullname.rs +71 −0
  15. git-ref/src/lib.rs +22 −6
  16. git-ref/src/mutable.rs +0 −162
  17. git-ref/src/name.rs +19 −19
  18. git-ref/src/namespace.rs +2 −2
  19. git-ref/src/store/file/find.rs +19 −16
  20. git-ref/src/store/file/log/iter.rs +6 −5
  21. git-ref/src/store/file/log/line.rs +71 −9
  22. git-ref/src/store/file/log/mod.rs +22 −86
  23. git-ref/src/store/file/loose/iter.rs +1 −1
  24. git-ref/src/store/file/loose/mod.rs +3 −3
  25. git-ref/src/store/file/loose/reference/decode.rs +8 −10
  26. git-ref/src/store/file/loose/reference/logiter.rs +4 −4
  27. git-ref/src/store/file/loose/reference/peel.rs +2 −2
  28. git-ref/src/store/file/loose/reflog.rs +8 −8
  29. git-ref/src/store/file/loose/reflog/create_or_update/tests.rs +6 −6
  30. git-ref/src/store/file/overlay.rs +1 −1
  31. git-ref/src/store/file/reference.rs +12 −13
  32. git-ref/src/store/file/transaction/commit.rs +2 −2
  33. git-ref/src/store/file/transaction/prepare.rs +6 −6
  34. git-ref/src/store/packed/decode.rs +1 −1
  35. git-ref/src/store/packed/decode/tests.rs +3 −3
  36. git-ref/src/store/packed/find.rs +6 −6
  37. git-ref/src/store/packed/mod.rs +2 −2
  38. git-ref/src/store/packed/transaction.rs +2 −4
  39. git-ref/src/target.rs +83 −8
  40. git-ref/src/transaction.rs +7 −7
  41. git-ref/tests/file/log.rs +5 −5
  42. git-ref/tests/file/reference.rs +16 −16
  43. git-ref/tests/file/store/find.rs +6 −6
  44. git-ref/tests/file/store/iter.rs +2 −2
  45. git-ref/tests/file/transaction/mod.rs +6 −5
  46. git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs +27 −28
  47. git-ref/tests/file/transaction/prepare_and_commit/delete.rs +31 −29
  48. git-ref/tests/packed/find.rs +25 −21
  49. git-ref/tests/packed/open.rs +1 −1
  50. git-ref/tests/transaction/mod.rs +5 −7
  51. git-repository/Cargo.toml +1 −1
  52. git-repository/src/easy/ext/reference.rs +4 −5
  53. git-repository/src/easy/reference.rs +5 −5
  54. git-repository/src/path/is_git.rs +1 −1
  55. git-repository/tests/reference/mod.rs +1 −1
  56. gitoxide-core/src/hours.rs +1 −1
  57. gitoxide-core/src/pack/create.rs +1 −1
Cargo.lock+1−1
@@ -985,7 +985,7 @@ dependencies = [ · 984 unmodified lines
985 985
986[[package]]986[[package]]
987name = "git-actor"987name = "git-actor"
988version = "0.4.0"988version = "0.5.0"
989dependencies = [989dependencies = [
990 "bstr",990 "bstr",
991 "btoi",991 "btoi",
cargo-smart-release/src/command/release/git.rs+2−5
@@ -141,7 +141,7 @@ pub(in crate::command::release_impl) fn create_version_tag<'repo>( · 140 unmodified lines
141 skip_tag,141 skip_tag,
142 ..142 ..
143 }: Options,143 }: Options,
144) -> anyhow::Result<Option<refs::mutable::FullName>> {144) -> anyhow::Result<Option<refs::FullName>> {
145 if skip_tag {145 if skip_tag {
146 return Ok(None);146 return Ok(None);
147 }147 }
@@ -170,10 +170,7 @@ pub(in crate::command::release_impl) fn create_version_tag<'repo>( · 22 unmodified lines
170}170}
171 171
172// TODO: Make this gitoxide172// TODO: Make this gitoxide
173pub fn push_tags_and_head(173pub fn push_tags_and_head(tag_names: impl IntoIterator<Item = refs::FullName>, options: Options) -> anyhow::Result<()> {
174 tag_names: impl IntoIterator<Item = refs::mutable::FullName>,
175 options: Options,
176) -> anyhow::Result<()> {
177 if options.skip_push {174 if options.skip_push {
178 return Ok(());175 return Ok(());
179 }176 }
experiments/diffing/src/main.rs+1−1
@@ -32,7 +32,7 @@ fn main() -> anyhow::Result<()> { · 31 unmodified lines
32 let packed = repo.refs.packed_buffer()?;32 let packed = repo.refs.packed_buffer()?;
33 let commit_id = repo33 let commit_id = repo
34 .refs34 .refs
35 .find_existing(&name, packed.as_ref())?35 .find(&name, packed.as_ref())?
36 .peel_to_id_in_place(&repo.refs, packed.as_ref(), peel::none)?36 .peel_to_id_in_place(&repo.refs, packed.as_ref(), peel::none)?
37 .to_owned();37 .to_owned();
38 let db = &repo.odb;38 let db = &repo.odb;
experiments/traversal/src/main.rs+1−1
@@ -28,7 +28,7 @@ fn main() -> anyhow::Result<()> { · 27 unmodified lines
28 let packed = repo.refs.packed_buffer()?;28 let packed = repo.refs.packed_buffer()?;
29 let commit_id = repo29 let commit_id = repo
30 .refs30 .refs
31 .find_existing(&name, packed.as_ref())?31 .find(&name, packed.as_ref())?
32 .peel_to_id_in_place(&repo.refs, packed.as_ref(), peel::none)?32 .peel_to_id_in_place(&repo.refs, packed.as_ref(), peel::none)?
33 .to_owned();33 .to_owned();
34 (repo, commit_id)34 (repo, commit_id)
git-actor/Cargo.toml+1−1
@@ -1,6 +1,6 @@
1[package]1[package]
2name = "git-actor"2name = "git-actor"
3version = "0.4.0"3version = "0.5.0"
4description = "A way to identify git actors"4description = "A way to identify git actors"
5authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]5authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
6repository = "https://github.com/Byron/gitoxide"6repository = "https://github.com/Byron/gitoxide"
git-actor/src/lib.rs+0−2
@@ -5,8 +5,6 @@ use bstr::{BStr, BString}; · 4 unmodified lines
5 5
6///6///
7pub mod signature;7pub mod signature;
8///
9pub mod signature_ref;
10 8
11const SPACE: &[u8; 1] = b" ";9const SPACE: &[u8; 1] = b" ";
12 10
git-actor/src/signature/decode.rsrenamed from git-actor/src/signature_ref/decode.rs+2−5
@@ -68,13 +68,10 @@ mod tests { · 67 unmodified lines
68 use git_testtools::to_bstr_err;68 use git_testtools::to_bstr_err;
69 use nom::IResult;69 use nom::IResult;
70 70
71 use crate::{71 use crate::{signature, Sign, SignatureRef, Time};
72 signature_ref::{self, SignatureRef},
73 Sign, Time,
74 };
75 72
76 fn decode(i: &[u8]) -> IResult<&[u8], SignatureRef<'_>, nom::error::VerboseError<&[u8]>> {73 fn decode(i: &[u8]) -> IResult<&[u8], SignatureRef<'_>, nom::error::VerboseError<&[u8]>> {
77 signature_ref::decode(i)74 signature::decode(i)
78 }75 }
79 76
80 fn signature(77 fn signature(
git-actor/src/signature/mod.rsrenamed from git-actor/src/signature.rs+17−0
@@ -1,3 +1,16 @@
1mod _ref {
2 use crate::{signature::decode, SignatureRef};
3
4 impl<'a> SignatureRef<'a> {
5 /// Deserialize a signature from the given `data`.
6 pub fn from_bytes<E: nom::error::ParseError<&'a [u8]> + nom::error::ContextError<&'a [u8]>>(
7 data: &'a [u8],
8 ) -> Result<SignatureRef<'a>, nom::Err<E>> {
9 decode(data).map(|(_, t)| t)
10 }
11 }
12}
13
1mod convert {14mod convert {
2 use crate::{Sign, Signature, SignatureRef, Time};15 use crate::{Sign, Signature, SignatureRef, Time};
3 16
@@ -85,3 +98,7 @@ mod write { · 81 unmodified lines
85 Ok(name)98 Ok(name)
86 }99 }
87}100}
101
102///
103mod decode;
104pub use decode::decode;
git-actor/src/signature_ref/mod.rs+0−14
@@ -1,14 +0,0 @@
1use crate::SignatureRef;
2
3impl<'a> SignatureRef<'a> {
4 /// Deserialize a signature from the given `data`.
5 pub fn from_bytes<E: nom::error::ParseError<&'a [u8]> + nom::error::ContextError<&'a [u8]>>(
6 data: &'a [u8],
7 ) -> Result<SignatureRef<'a>, nom::Err<E>> {
8 decode(data).map(|(_, t)| t)
9 }
10}
11
12///
13mod decode;
14pub use decode::decode;
git-object/Cargo.toml+1−1
@@ -21,7 +21,7 @@ all-features = true · 20 unmodified lines
21[dependencies]21[dependencies]
22git-hash = { version = "^0.5.0", path = "../git-hash" }22git-hash = { version = "^0.5.0", path = "../git-hash" }
23git-validate = { version = "^0.5.0", path = "../git-validate" }23git-validate = { version = "^0.5.0", path = "../git-validate" }
24git-actor = { version ="^0.4.0", path = "../git-actor" }24git-actor = { version ="^0.5.0", path = "../git-actor" }
25 25
26quick-error = "2.0.0"26quick-error = "2.0.0"
27hex = "0.4.2"27hex = "0.4.2"
git-object/src/immutable/parse.rs+1−1
@@ -77,5 +77,5 @@ pub fn hex_hash<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], & · 76 unmodified lines
77pub(crate) fn signature<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(77pub(crate) fn signature<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
78 i: &'a [u8],78 i: &'a [u8],
79) -> IResult<&'a [u8], git_actor::SignatureRef<'a>, E> {79) -> IResult<&'a [u8], git_actor::SignatureRef<'a>, E> {
80 git_actor::signature_ref::decode(i)80 git_actor::signature::decode(i)
81}81}
git-object/src/types.rs+1−1
@@ -56,7 +56,7 @@ impl fmt::Display for Kind { · 55 unmodified lines
56pub mod tree {56pub mod tree {
57 /// The mode of items storable in a tree, similar to the file mode on a unix file system.57 /// The mode of items storable in a tree, similar to the file mode on a unix file system.
58 ///58 ///
59 /// Used in [mutable::Entry][crate::mutable::tree::Entry] and [signature_ref::Entry][crate::immutable::tree::Entry].59 /// Used in [mutable::Entry][crate::mutable::tree::Entry] and [tree::Entry][crate::immutable::tree::Entry].
60 #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)]60 #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)]
61 #[repr(u16)]61 #[repr(u16)]
62 #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]62 #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
git-ref/Cargo.toml+1−1
@@ -28,7 +28,7 @@ git-features = { version = "^0.16.0", path = "../git-features", features = ["wal · 27 unmodified lines
28git-hash = { version = "^0.5.0", path = "../git-hash" }28git-hash = { version = "^0.5.0", path = "../git-hash" }
29git-object = { version ="0.12.0", path = "../git-object" }29git-object = { version ="0.12.0", path = "../git-object" }
30git-validate = { version = "^0.5.0", path = "../git-validate" }30git-validate = { version = "^0.5.0", path = "../git-validate" }
31git-actor = { version ="^0.4.0", path = "../git-actor" }31git-actor = { version ="^0.5.0", path = "../git-actor" }
32git-lock = { version ="^1.0.0", path = "../git-lock" }32git-lock = { version ="^1.0.0", path = "../git-lock" }
33git-tempfile = { version ="^1.0.0", path = "../git-tempfile" }33git-tempfile = { version ="^1.0.0", path = "../git-tempfile" }
34 34
git-ref/src/fullname.rs+71−0
@@ -0,0 +1,71 @@
1use std::{borrow::Cow, convert::TryFrom, path::Path};
2
3use bstr::{BStr, BString, ByteSlice};
4
5use crate::FullName;
6
7impl TryFrom<&str> for FullName {
8 type Error = git_validate::refname::Error;
9
10 fn try_from(value: &str) -> Result<Self, Self::Error> {
11 Ok(FullName(git_validate::refname(value.as_bytes().as_bstr())?.into()))
12 }
13}
14
15impl TryFrom<String> for FullName {
16 type Error = git_validate::refname::Error;
17
18 fn try_from(value: String) -> Result<Self, Self::Error> {
19 git_validate::refname(value.as_bytes().as_bstr())?;
20 Ok(FullName(value.into()))
21 }
22}
23
24impl TryFrom<&BStr> for FullName {
25 type Error = git_validate::refname::Error;
26
27 fn try_from(value: &BStr) -> Result<Self, Self::Error> {
28 Ok(FullName(git_validate::refname(value)?.into()))
29 }
30}
31
32impl TryFrom<BString> for FullName {
33 type Error = git_validate::refname::Error;
34
35 fn try_from(value: BString) -> Result<Self, Self::Error> {
36 git_validate::refname(value.as_ref())?;
37 Ok(FullName(value))
38 }
39}
40
41impl<'a> From<crate::FullNameRef<'a>> for FullName {
42 fn from(value: crate::FullNameRef<'a>) -> Self {
43 FullName(value.as_bstr().into())
44 }
45}
46
47impl FullName {
48 /// Interpret this fully qualified reference name as partial name.
49 pub fn to_partial(&self) -> crate::PartialNameRef<'_> {
50 crate::PartialNameRef(self.0.as_bstr())
51 }
52
53 /// Interpret this fully qualified reference as shared full name
54 pub fn to_ref(&self) -> crate::FullNameRef<'_> {
55 crate::FullNameRef(self.0.as_bstr())
56 }
57
58 /// Convert this name into the relative path, lossily, identifying the reference location relative to a repository
59 pub fn to_path(&self) -> Cow<'_, Path> {
60 self.0.to_path().expect("UTF-8 conversion always succeeds").into()
61 }
62
63 /// Dissolve this instance and return the buffer.
64 pub fn into_inner(self) -> BString {
65 self.0
66 }
67 /// Return ourselves as byte string which is a valid refname
68 pub fn as_bstr(&self) -> &BStr {
69 self.0.as_bstr()
70 }
71}
git-ref/src/lib.rs+22−6
@@ -19,12 +19,12 @@ · 18 unmodified lines
19#![forbid(unsafe_code)]19#![forbid(unsafe_code)]
20#![deny(missing_docs, rust_2018_idioms)]20#![deny(missing_docs, rust_2018_idioms)]
21use bstr::{BStr, BString};21use bstr::{BStr, BString};
22use git_hash::oid;22use git_hash::{oid, ObjectId};
23 23
24mod store;24mod store;
25pub use store::{file, packed};25pub use store::{file, packed};
26///26
27pub mod mutable;27mod fullname;
28///28///
29pub mod name;29pub mod name;
30///30///
@@ -32,12 +32,17 @@ pub mod namespace; · 1 unmodified line
32///32///
33pub mod transaction;33pub mod transaction;
34 34
35/// Indicate that the given BString is a validate reference name or path that can be used as path on disk or written as target
36/// of a symbolic reference
37#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
38pub struct FullName(pub(crate) BString);
39
35/// A validated and potentially partial reference name - it can safely be used for common operations.40/// A validated and potentially partial reference name - it can safely be used for common operations.
36#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]41#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
37pub struct FullName<'a>(&'a BStr);42pub struct FullNameRef<'a>(&'a BStr);
38/// A validated complete and fully qualified reference name, safe to use for all operations.43/// A validated complete and fully qualified reference name, safe to use for all operations.
39#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]44#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
40pub struct PartialName<'a>(&'a BStr);45pub struct PartialNameRef<'a>(&'a BStr);
41 46
42/// A validated prefix for references to act as a namespace.47/// A validated prefix for references to act as a namespace.
43#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]48#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
@@ -55,9 +60,20 @@ pub enum Kind { · 11 unmodified lines
55 Symbolic,60 Symbolic,
56}61}
57 62
63/// Denotes a ref target, equivalent to [`Kind`], but with mutable data.
64#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
65pub enum Target {
66 /// A ref that points to an object id
67 Peeled(ObjectId),
68 /// A ref that points to another reference by its validated name, adding a level of indirection.
69 ///
70 /// Note that this is an extension of gitoxide which will be helpful in logging all reference changes.
71 Symbolic(FullName),
72}
73
58/// Denotes a ref target, equivalent to [`Kind`], but with signature_ref data.74/// Denotes a ref target, equivalent to [`Kind`], but with signature_ref data.
59#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]75#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
60pub enum Target<'a> {76pub enum TargetRef<'a> {
61 /// A ref that points to an object id77 /// A ref that points to an object id
62 Peeled(&'a oid),78 Peeled(&'a oid),
63 /// A ref that points to another reference by its validated name, adding a level of indirection.79 /// A ref that points to another reference by its validated name, adding a level of indirection.
git-ref/src/mutable.rs+0−162
@@ -1,162 +0,0 @@
1use std::{borrow::Cow, convert::TryFrom, fmt, path::Path};
2
3use bstr::{BStr, BString, ByteSlice};
4use git_hash::{oid, ObjectId};
5
6use crate::Kind;
7
8/// Indicate that the given BString is a validate reference name or path that can be used as path on disk or written as target
9/// of a symbolic reference
10#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
11pub struct FullName(pub(crate) BString);
12
13impl TryFrom<&str> for FullName {
14 type Error = git_validate::refname::Error;
15
16 fn try_from(value: &str) -> Result<Self, Self::Error> {
17 Ok(FullName(git_validate::refname(value.as_bytes().as_bstr())?.into()))
18 }
19}
20
21impl TryFrom<String> for FullName {
22 type Error = git_validate::refname::Error;
23
24 fn try_from(value: String) -> Result<Self, Self::Error> {
25 git_validate::refname(value.as_bytes().as_bstr())?;
26 Ok(FullName(value.into()))
27 }
28}
29
30impl TryFrom<&BStr> for FullName {
31 type Error = git_validate::refname::Error;
32
33 fn try_from(value: &BStr) -> Result<Self, Self::Error> {
34 Ok(FullName(git_validate::refname(value)?.into()))
35 }
36}
37
38impl TryFrom<BString> for FullName {
39 type Error = git_validate::refname::Error;
40
41 fn try_from(value: BString) -> Result<Self, Self::Error> {
42 git_validate::refname(value.as_ref())?;
43 Ok(FullName(value))
44 }
45}
46
47impl<'a> From<crate::FullName<'a>> for FullName {
48 fn from(value: crate::FullName<'a>) -> Self {
49 FullName(value.as_bstr().into())
50 }
51}
52
53impl FullName {
54 /// Interpret this fully qualified reference name as partial name.
55 pub fn to_partial(&self) -> crate::PartialName<'_> {
56 crate::PartialName(self.0.as_bstr())
57 }
58
59 /// Interpret this fully qualified reference as shared full name
60 pub fn borrow(&self) -> crate::FullName<'_> {
61 crate::FullName(self.0.as_bstr())
62 }
63
64 /// Convert this name into the relative path, lossily, identifying the reference location relative to a repository
65 pub fn to_path(&self) -> Cow<'_, Path> {
66 self.0.to_path().expect("UTF-8 conversion always succeeds").into()
67 }
68
69 /// Dissolve this instance and return the buffer.
70 pub fn into_inner(self) -> BString {
71 self.0
72 }
73 /// Return ourselves as byte string which is a valid refname
74 pub fn as_bstr(&self) -> &BStr {
75 self.0.as_bstr()
76 }
77}
78
79/// Denotes a ref target, equivalent to [`Kind`][super::Kind], but with mutable data.
80#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
81pub enum Target {
82 /// A ref that points to an object id
83 Peeled(ObjectId),
84 /// A ref that points to another reference by its validated name, adding a level of indirection.
85 ///
86 /// Note that this is an extension of gitoxide which will be helpful in logging all reference changes.
87 Symbolic(FullName),
88}
89
90impl Target {
91 /// Returns the kind of the target the ref is pointing to.
92 pub fn kind(&self) -> Kind {
93 match self {
94 Target::Symbolic(_) => Kind::Symbolic,
95 Target::Peeled(_) => Kind::Peeled,
96 }
97 }
98
99 /// Return true if this is a peeled target with a null hash
100 pub fn is_null(&self) -> bool {
101 match self {
102 Target::Peeled(oid) => oid.is_null(),
103 Target::Symbolic(_) => false,
104 }
105 }
106
107 /// Interpret this owned Target as shared Target
108 pub fn borrow(&self) -> crate::Target<'_> {
109 match self {
110 Target::Peeled(oid) => crate::Target::Peeled(oid),
111 Target::Symbolic(name) => crate::Target::Symbolic(name.0.as_bstr()),
112 }
113 }
114
115 /// Interpret this target as object id which maybe `None` if it is symbolic.
116 pub fn as_id(&self) -> Option<&oid> {
117 match self {
118 Target::Symbolic(_) => None,
119 Target::Peeled(oid) => Some(oid),
120 }
121 }
122 /// Interpret this target as name of the reference it points to which maybe `None` if it an object id.
123 pub fn as_name(&self) -> Option<&BStr> {
124 match self {
125 Target::Symbolic(name) => Some(name.as_bstr()),
126 Target::Peeled(_) => None,
127 }
128 }
129
130 /// Create an instance that signals that a reference should exist if this value is used in a [`Change`][crate::transaction::Change].
131 pub fn must_exist() -> Self {
132 Target::Peeled(ObjectId::null_sha1())
133 }
134}
135
136impl<'a> From<crate::Target<'a>> for Target {
137 fn from(src: crate::Target<'a>) -> Self {
138 match src {
139 crate::Target::Peeled(oid) => Target::Peeled(oid.to_owned()),
140 crate::Target::Symbolic(name) => Target::Symbolic(FullName(name.to_owned())),
141 }
142 }
143}
144
145impl<'a> PartialEq<crate::Target<'a>> for Target {
146 fn eq(&self, other: &crate::Target<'a>) -> bool {
147 match (self, other) {
148 (Target::Peeled(lhs), crate::Target::Peeled(rhs)) => lhs == rhs,
149 (Target::Symbolic(lhs), crate::Target::Symbolic(rhs)) => lhs.as_bstr() == *rhs,
150 _ => false,
151 }
152 }
153}
154
155impl fmt::Display for Target {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 match self {
158 Target::Peeled(oid) => oid.fmt(f),
159 Target::Symbolic(name) => write!(f, "ref: {}", name.as_bstr()),
160 }
161 }
162}
git-ref/src/name.rs+19−19
@@ -6,12 +6,12 @@ use std::{ · 5 unmodified lines
6 6
7use bstr::{BStr, ByteSlice};7use bstr::{BStr, ByteSlice};
8 8
9use crate::{FullName, PartialName};9use crate::{FullNameRef, PartialNameRef};
10 10
11/// The error used in the [`PartialName`][super::PartialName]::try_from(…) implementations.11/// The error used in the [`PartialNameRef`][super::PartialNameRef]::try_from(…) implementations.
12pub type Error = git_validate::reference::name::Error;12pub type Error = git_validate::reference::name::Error;
13 13
14impl<'a> FullName<'a> {14impl<'a> FullNameRef<'a> {
15 /// Convert this name into the relative path identifying the reference location.15 /// Convert this name into the relative path identifying the reference location.
16 pub fn to_path(self) -> Cow<'a, Path> {16 pub fn to_path(self) -> Cow<'a, Path> {
17 self.0.to_path().expect("UTF-8 conversion always succeeds").into()17 self.0.to_path().expect("UTF-8 conversion always succeeds").into()
@@ -23,7 +23,7 @@ impl<'a> FullName<'a> { · 5 unmodified lines
23 }23 }
24}24}
25 25
26impl<'a> PartialName<'a> {26impl<'a> PartialNameRef<'a> {
27 /// Convert this name into the relative path possibly identifying the reference location.27 /// Convert this name into the relative path possibly identifying the reference location.
28 /// Note that it may be only a partial path though.28 /// Note that it may be only a partial path though.
29 pub fn to_partial_path(self) -> Cow<'a, Path> {29 pub fn to_partial_path(self) -> Cow<'a, Path> {
@@ -36,62 +36,62 @@ impl<'a> PartialName<'a> { · 6 unmodified lines
36 }36 }
37}37}
38 38
39impl<'a> TryFrom<&'a BStr> for FullName<'a> {39impl<'a> TryFrom<&'a BStr> for FullNameRef<'a> {
40 type Error = Error;40 type Error = Error;
41 41
42 fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {42 fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {
43 Ok(FullName(git_validate::reference::name(v)?))43 Ok(FullNameRef(git_validate::reference::name(v)?))
44 }44 }
45}45}
46 46
47impl<'a> TryFrom<FullName<'a>> for PartialName<'a> {47impl<'a> TryFrom<FullNameRef<'a>> for PartialNameRef<'a> {
48 type Error = Infallible;48 type Error = Infallible;
49 49
50 fn try_from(v: FullName<'a>) -> Result<Self, Self::Error> {50 fn try_from(v: FullNameRef<'a>) -> Result<Self, Self::Error> {
51 Ok(PartialName(v.0))51 Ok(PartialNameRef(v.0))
52 }52 }
53}53}
54 54
55impl<'a> TryFrom<&'a BStr> for PartialName<'a> {55impl<'a> TryFrom<&'a BStr> for PartialNameRef<'a> {
56 type Error = Error;56 type Error = Error;
57 57
58 fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {58 fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {
59 Ok(PartialName(git_validate::reference::name_partial(v)?))59 Ok(PartialNameRef(git_validate::reference::name_partial(v)?))
60 }60 }
61}61}
62 62
63impl<'a> TryFrom<&'a str> for FullName<'a> {63impl<'a> TryFrom<&'a str> for FullNameRef<'a> {
64 type Error = Error;64 type Error = Error;
65 65
66 fn try_from(v: &'a str) -> Result<Self, Self::Error> {66 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
67 let v = v.as_bytes().as_bstr();67 let v = v.as_bytes().as_bstr();
68 Ok(FullName(git_validate::reference::name(v)?))68 Ok(FullNameRef(git_validate::reference::name(v)?))
69 }69 }
70}70}
71 71
72impl<'a> TryFrom<&'a str> for PartialName<'a> {72impl<'a> TryFrom<&'a str> for PartialNameRef<'a> {
73 type Error = Error;73 type Error = Error;
74 74
75 fn try_from(v: &'a str) -> Result<Self, Self::Error> {75 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
76 let v = v.as_bytes().as_bstr();76 let v = v.as_bytes().as_bstr();
77 Ok(PartialName(git_validate::reference::name_partial(v)?))77 Ok(PartialNameRef(git_validate::reference::name_partial(v)?))
78 }78 }
79}79}
80 80
81impl<'a> TryFrom<&'a String> for FullName<'a> {81impl<'a> TryFrom<&'a String> for FullNameRef<'a> {
82 type Error = Error;82 type Error = Error;
83 83
84 fn try_from(v: &'a String) -> Result<Self, Self::Error> {84 fn try_from(v: &'a String) -> Result<Self, Self::Error> {
85 let v = v.as_bytes().as_bstr();85 let v = v.as_bytes().as_bstr();
86 Ok(FullName(git_validate::reference::name(v)?))86 Ok(FullNameRef(git_validate::reference::name(v)?))
87 }87 }
88}88}
89 89
90impl<'a> TryFrom<&'a String> for PartialName<'a> {90impl<'a> TryFrom<&'a String> for PartialNameRef<'a> {
91 type Error = Error;91 type Error = Error;
92 92
93 fn try_from(v: &'a String) -> Result<Self, Self::Error> {93 fn try_from(v: &'a String) -> Result<Self, Self::Error> {
94 let v = v.as_bytes().as_bstr();94 let v = v.as_bytes().as_bstr();
95 Ok(PartialName(git_validate::reference::name_partial(v)?))95 Ok(PartialNameRef(git_validate::reference::name_partial(v)?))
96 }96 }
97}97}
git-ref/src/namespace.rs+2−2
@@ -2,7 +2,7 @@ use std::{borrow::Cow, convert::TryInto, path::Path}; · 1 unmodified line
2 2
3use bstr::{BStr, BString, ByteSlice, ByteVec};3use bstr::{BStr, BString, ByteSlice, ByteVec};
4 4
5use crate::{Namespace, PartialName};5use crate::{Namespace, PartialNameRef};
6 6
7impl Namespace {7impl Namespace {
8 /// Dissolve ourselves into the interior representation8 /// Dissolve ourselves into the interior representation
@@ -24,7 +24,7 @@ impl Namespace { · 15 unmodified lines
24/// For more information, consult the [git namespace documentation](https://git-scm.com/docs/gitnamespaces).24/// For more information, consult the [git namespace documentation](https://git-scm.com/docs/gitnamespaces).
25pub fn expand<'a, Name, E>(namespace: Name) -> Result<Namespace, git_validate::refname::Error>25pub fn expand<'a, Name, E>(namespace: Name) -> Result<Namespace, git_validate::refname::Error>
26where26where
27 Name: TryInto<PartialName<'a>, Error = E>,27 Name: TryInto<PartialNameRef<'a>, Error = E>,
28 git_validate::refname::Error: From<E>,28 git_validate::refname::Error: From<E>,
29{29{
30 let namespace = namespace.try_into()?.0;30 let namespace = namespace.try_into()?.0;
git-ref/src/store/file/find.rs+19−16
@@ -9,12 +9,11 @@ pub use error::Error; · 8 unmodified lines
9 9
10use crate::{10use crate::{
11 file,11 file,
12 mutable::FullName,
13 store::{12 store::{
14 file::{loose, path_to_name},13 file::{loose, path_to_name},
15 packed,14 packed,
16 },15 },
17 PartialName,16 FullName, PartialNameRef,
18};17};
19 18
20enum Transform {19enum Transform {
@@ -35,13 +34,13 @@ impl file::Store { · 14 unmodified lines
35 /// The lookup algorithm follows the one in [the git documentation][git-lookup-docs].34 /// The lookup algorithm follows the one in [the git documentation][git-lookup-docs].
36 ///35 ///
37 /// [git-lookup-docs]: https://github.com/git/git/blob/5d5b1473453400224ebb126bf3947e0a3276bdf5/Documentation/revisions.txt#L34-L4636 /// [git-lookup-docs]: https://github.com/git/git/blob/5d5b1473453400224ebb126bf3947e0a3276bdf5/Documentation/revisions.txt#L34-L46
38 pub fn find<'a, 'p, 's, Name, E>(37 pub fn try_find<'a, 'p, 's, Name, E>(
39 &'s self,38 &'s self,
40 partial: Name,39 partial: Name,
41 packed: Option<&'p packed::Buffer>,40 packed: Option<&'p packed::Buffer>,
42 ) -> Result<Option<file::Reference<'p>>, Error>41 ) -> Result<Option<file::Reference<'p>>, Error>
43 where42 where
44 Name: TryInto<PartialName<'a>, Error = E>,43 Name: TryInto<PartialNameRef<'a>, Error = E>,
45 Error: From<E>,44 Error: From<E>,
46 {45 {
47 let path = partial.try_into()?;46 let path = partial.try_into()?;
@@ -49,12 +48,16 @@ impl file::Store { · 1 unmodified line
49 }48 }
50 49
51 /// Similar to [`file::Store::find()`] but a non-existing ref is treated as error.50 /// Similar to [`file::Store::find()`] but a non-existing ref is treated as error.
52 pub fn loose_find<'a, Name, E>(&self, partial: Name) -> Result<Option<loose::Reference>, Error>51 ///
52 /// Find only loose references, that is references that aren't in the packed-refs buffer.
53 /// All symbolic references are loose references.
54 /// `HEAD` is always a loose reference.
55 pub fn try_find_loose<'a, Name, E>(&self, partial: Name) -> Result<Option<loose::Reference>, Error>
53 where56 where
54 Name: TryInto<PartialName<'a>, Error = E>,57 Name: TryInto<PartialNameRef<'a>, Error = E>,
55 Error: From<E>,58 Error: From<E>,
56 {59 {
57 self.find(partial, None)60 self.try_find(partial, None)
58 .map(|r| r.map(|r| r.try_into().expect("only loose refs are found without pack")))61 .map(|r| r.map(|r| r.try_into().expect("only loose refs are found without pack")))
59 }62 }
60 63
@@ -116,8 +119,8 @@ impl file::Store { · 55 unmodified lines
116 if is_definitely_absolute {119 if is_definitely_absolute {
117 if let Some(packed) = packed {120 if let Some(packed) = packed {
118 let full_name = path_to_name(relative_path);121 let full_name = path_to_name(relative_path);
119 let full_name = PartialName((*full_name).as_bstr());122 let full_name = PartialNameRef((*full_name).as_bstr());
120 if let Some(packed_ref) = packed.find(full_name)? {123 if let Some(packed_ref) = packed.try_find(full_name)? {
121 return Ok(Some(file::Reference::Packed(packed_ref)));124 return Ok(Some(file::Reference::Packed(packed_ref)));
122 };125 };
123 }126 }
@@ -173,18 +176,18 @@ pub mod existing { · 49 unmodified lines
173 file::{find, loose},176 file::{find, loose},
174 packed,177 packed,
175 },178 },
176 PartialName,179 PartialNameRef,
177 };180 };
178 181
179 impl file::Store {182 impl file::Store {
180 /// Similar to [`file::Store::find_existing()`] but a non-existing ref is treated as error.183 /// Similar to [`file::Store::find()`] but a non-existing ref is treated as error.
181 pub fn find_existing<'a, 'p, 's, Name, E>(184 pub fn find<'a, 'p, 's, Name, E>(
182 &'s self,185 &'s self,
183 partial: Name,186 partial: Name,
184 packed: Option<&'p packed::Buffer>,187 packed: Option<&'p packed::Buffer>,
185 ) -> Result<file::Reference<'p>, Error>188 ) -> Result<file::Reference<'p>, Error>
186 where189 where
187 Name: TryInto<PartialName<'a>, Error = E>,190 Name: TryInto<PartialNameRef<'a>, Error = E>,
188 crate::name::Error: From<E>,191 crate::name::Error: From<E>,
189 {192 {
190 let path = partial193 let path = partial
@@ -198,12 +201,12 @@ pub mod existing { · 7 unmodified lines
198 }201 }
199 202
200 /// Similar to [`file::Store::find()`] won't handle packed-refs.203 /// Similar to [`file::Store::find()`] won't handle packed-refs.
201 pub fn loose_find_existing<'a, Name, E>(&self, partial: Name) -> Result<loose::Reference, Error>204 pub fn find_loose<'a, Name, E>(&self, partial: Name) -> Result<loose::Reference, Error>
202 where205 where
203 Name: TryInto<PartialName<'a>, Error = E>,206 Name: TryInto<PartialNameRef<'a>, Error = E>,
204 crate::name::Error: From<E>,207 crate::name::Error: From<E>,
205 {208 {
206 self.find_existing(partial, None)209 self.find(partial, None)
207 .map(|r| r.try_into().expect("always loose without packed"))210 .map(|r| r.try_into().expect("always loose without packed"))
208 }211 }
209 }212 }
git-ref/src/store/file/log/iter.rs+6−5
@@ -1,5 +1,6 @@
1use bstr::ByteSlice;1use bstr::ByteSlice;
2 2
3use crate::store::file;
3use crate::store::file::{log, log::iter::decode::LineNumber};4use crate::store::file::{log, log::iter::decode::LineNumber};
4 5
5///6///
@@ -51,9 +52,9 @@ pub mod decode { · 45 unmodified lines
51/// This iterator is useful when the ref log file is going to be rewritten which forces processing of the entire file.52/// This iterator is useful when the ref log file is going to be rewritten which forces processing of the entire file.
52/// It will continue parsing even if individual log entries failed to parse, leaving it to the driver to decide whether to53/// It will continue parsing even if individual log entries failed to parse, leaving it to the driver to decide whether to
53/// abort or continue.54/// abort or continue.
54pub fn forward(lines: &[u8]) -> impl Iterator<Item = Result<log::Line<'_>, decode::Error>> {55pub fn forward(lines: &[u8]) -> impl Iterator<Item = Result<log::LineRef<'_>, decode::Error>> {
55 lines.as_bstr().lines().enumerate().map(|(ln, line)| {56 lines.as_bstr().lines().enumerate().map(|(ln, line)| {
56 log::Line::from_bytes(line).map_err(|err| decode::Error::new(err, decode::LineNumber::FromStart(ln)))57 log::LineRef::from_bytes(line).map_err(|err| decode::Error::new(err, decode::LineNumber::FromStart(ln)))
57 })58 })
58}59}
59 60
@@ -93,7 +94,7 @@ impl<'a, F> Iterator for Reverse<'a, F> · 33 unmodified lines
93where94where
94 F: std::io::Read + std::io::Seek,95 F: std::io::Read + std::io::Seek,
95{96{
96 type Item = std::io::Result<Result<log::mutable::Line, decode::Error>>;97 type Item = std::io::Result<Result<file::log::Line, decode::Error>>;
97 98
98 fn next(&mut self) -> Option<Self::Item> {99 fn next(&mut self) -> Option<Self::Item> {
99 match (self.last_nl_pos.take(), self.read_and_pos.take()) {100 match (self.last_nl_pos.take(), self.read_and_pos.take()) {
@@ -124,7 +125,7 @@ where · 24 unmodified lines
124 self.read_and_pos = Some(read_and_pos);125 self.read_and_pos = Some(read_and_pos);
125 self.last_nl_pos = Some(start);126 self.last_nl_pos = Some(start);
126 let buf = &self.buf[start + 1..end];127 let buf = &self.buf[start + 1..end];
127 let res = Some(Ok(log::Line::from_bytes(buf)128 let res = Some(Ok(log::LineRef::from_bytes(buf)
128 .map_err(|err| decode::Error::new(err, LineNumber::FromEnd(self.count)))129 .map_err(|err| decode::Error::new(err, LineNumber::FromEnd(self.count)))
129 .map(Into::into)));130 .map(Into::into)));
130 self.count += 1;131 self.count += 1;
@@ -134,7 +135,7 @@ where · 3 unmodified lines
134 let (mut read, last_read_pos) = read_and_pos;135 let (mut read, last_read_pos) = read_and_pos;
135 if last_read_pos == 0 {136 if last_read_pos == 0 {
136 let buf = &self.buf[..end];137 let buf = &self.buf[..end];
137 Some(Ok(log::Line::from_bytes(buf)138 Some(Ok(log::LineRef::from_bytes(buf)
138 .map_err(|err| decode::Error::new(err, LineNumber::FromEnd(self.count)))139 .map_err(|err| decode::Error::new(err, LineNumber::FromEnd(self.count)))
139 .map(Into::into)))140 .map(Into::into)))
140 } else {141 } else {
git-ref/src/store/file/log/line.rs+71−9
@@ -1,8 +1,59 @@
1use git_hash::ObjectId;1use git_hash::ObjectId;
2 2
3use crate::store::file::log::Line;3use crate::store::file::log::Line;
4use crate::store::file::log::LineRef;
4 5
5impl<'a> Line<'a> {6impl<'a> LineRef<'a> {
7 /// Convert this instance into its mutable counterpart
8 pub fn to_owned(&self) -> Line {
9 self.clone().into()
10 }
11}
12
13mod write {
14 use std::io;
15
16 use bstr::{BStr, ByteSlice};
17 use quick_error::quick_error;
18
19 use crate::store::file::log::Line;
20
21 quick_error! {
22 /// The Error produced by [`Line::write_to()`] (but wrapped in an io error).
23 #[derive(Debug)]
24 #[allow(missing_docs)]
25 enum Error {
26 IllegalCharacter {
27 display("Messages must not contain newlines\\n")
28 }
29 }
30 }
31
32 impl From<Error> for io::Error {
33 fn from(err: Error) -> Self {
34 io::Error::new(io::ErrorKind::Other, err)
35 }
36 }
37
38 /// Output
39 impl Line {
40 /// Serialize this instance to `out` in the git serialization format for ref log lines.
41 pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> {
42 write!(out, "{} {} ", self.previous_oid, self.new_oid)?;
43 self.signature.write_to(&mut out)?;
44 writeln!(out, "\t{}", check_newlines(self.message.as_ref())?)
45 }
46 }
47
48 fn check_newlines(input: &BStr) -> Result<&BStr, Error> {
49 if input.find_byte(b'\n').is_some() {
50 return Err(Error::IllegalCharacter);
51 }
52 Ok(input)
53 }
54}
55
56impl<'a> LineRef<'a> {
6 /// The previous object id of the ref. It will be a null hash if there was no previous id as57 /// The previous object id of the ref. It will be a null hash if there was no previous id as
7 /// this ref is being created.58 /// this ref is being created.
8 pub fn previous_oid(&self) -> ObjectId {59 pub fn previous_oid(&self) -> ObjectId {
@@ -14,6 +65,17 @@ impl<'a> Line<'a> { · 5 unmodified lines
14 }65 }
15}66}
16 67
68impl<'a> From<LineRef<'a>> for Line {
69 fn from(v: LineRef<'a>) -> Self {
70 Line {
71 previous_oid: v.previous_oid(),
72 new_oid: v.new_oid(),
73 signature: v.signature.into(),
74 message: v.message.into(),
75 }
76 }
77}
78
17///79///
18pub mod decode {80pub mod decode {
19 use bstr::{BStr, ByteSlice};81 use bstr::{BStr, ByteSlice};
@@ -25,7 +87,7 @@ pub mod decode { · 5 unmodified lines
25 IResult,87 IResult,
26 };88 };
27 89
28 use crate::{file::log::Line, parse::hex_hash};90 use crate::{file::log::LineRef, parse::hex_hash};
29 91
30 ///92 ///
31 mod error {93 mod error {
@@ -59,9 +121,9 @@ pub mod decode { · 27 unmodified lines
59 }121 }
60 pub use error::Error;122 pub use error::Error;
61 123
62 impl<'a> Line<'a> {124 impl<'a> LineRef<'a> {
63 /// Decode a line from the given bytes which are expected to start at a hex sha.125 /// Decode a line from the given bytes which are expected to start at a hex sha.
64 pub fn from_bytes(input: &'a [u8]) -> Result<Line<'a>, Error> {126 pub fn from_bytes(input: &'a [u8]) -> Result<LineRef<'a>, Error> {
65 one::<()>(input).map(|(_, l)| l).map_err(|_| Error::new(input))127 one::<()>(input).map(|(_, l)| l).map_err(|_| Error::new(input))
66 }128 }
67 }129 }
@@ -74,13 +136,13 @@ pub mod decode { · 6 unmodified lines
74 }136 }
75 }137 }
76 138
77 fn one<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(bytes: &'a [u8]) -> IResult<&[u8], Line<'a>, E> {139 fn one<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(bytes: &'a [u8]) -> IResult<&[u8], LineRef<'a>, E> {
78 let (i, (old, new, signature, message_sep, message)) = context(140 let (i, (old, new, signature, message_sep, message)) = context(
79 "<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>",141 "<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>",
80 tuple((142 tuple((
81 context("<old-hexsha>", terminated(hex_hash, tag(b" "))),143 context("<old-hexsha>", terminated(hex_hash, tag(b" "))),
82 context("<new-hexsha>", terminated(hex_hash, tag(b" "))),144 context("<new-hexsha>", terminated(hex_hash, tag(b" "))),
83 context("<name> <<email>> <timestamp>", git_actor::signature_ref::decode),145 context("<name> <<email>> <timestamp>", git_actor::signature::decode),
84 opt(tag(b"\t")),146 opt(tag(b"\t")),
85 context("<optional message>", message),147 context("<optional message>", message),
86 )),148 )),
@@ -100,7 +162,7 @@ pub mod decode { · 13 unmodified lines
100 162
101 Ok((163 Ok((
102 i,164 i,
103 Line {165 LineRef {
104 previous_oid: old,166 previous_oid: old,
105 new_oid: new,167 new_oid: new,
106 signature,168 signature,
@@ -161,7 +223,7 @@ pub mod decode { · 54 unmodified lines
161 for input in &[line_without_nl, line_with_nl] {223 for input in &[line_without_nl, line_with_nl] {
162 assert_eq!(224 assert_eq!(
163 one::<nom::error::Error<_>>(input).expect("successful parsing").1,225 one::<nom::error::Error<_>>(input).expect("successful parsing").1,
164 Line {226 LineRef {
165 previous_oid: NULL_SHA1.as_bstr(),227 previous_oid: NULL_SHA1.as_bstr(),
166 new_oid: NULL_SHA1.as_bstr(),228 new_oid: NULL_SHA1.as_bstr(),
167 signature: git_actor::SignatureRef {229 signature: git_actor::SignatureRef {
@@ -187,7 +249,7 @@ pub mod decode { · 19 unmodified lines
187 for input in &[line_without_nl, line_with_nl] {249 for input in &[line_without_nl, line_with_nl] {
188 let (remaining, res) = one::<nom::error::Error<_>>(input).expect("successful parsing");250 let (remaining, res) = one::<nom::error::Error<_>>(input).expect("successful parsing");
189 assert!(remaining.is_empty(), "all consuming even without trailing newline");251 assert!(remaining.is_empty(), "all consuming even without trailing newline");
190 let actual = Line {252 let actual = LineRef {
191 previous_oid: b"a5828ae6b52137b913b978e16cd2334482eb4c1f".as_bstr(),253 previous_oid: b"a5828ae6b52137b913b978e16cd2334482eb4c1f".as_bstr(),
192 new_oid: b"89b43f80a514aee58b662ad606e6352e03eaeee4".as_bstr(),254 new_oid: b"89b43f80a514aee58b662ad606e6352e03eaeee4".as_bstr(),
193 signature: git_actor::SignatureRef {255 signature: git_actor::SignatureRef {
git-ref/src/store/file/log/mod.rs+22−86
@@ -1,15 +1,22 @@
1use bstr::BStr;1use bstr::BStr;
2 2
3use git_hash::ObjectId;
4use git_object::bstr::BString;
5
3pub use super::loose::reflog::{create_or_update, Error};6pub use super::loose::reflog::{create_or_update, Error};
4 7
8///
9pub mod iter;
10mod line;
11
5/// A parsed ref log line.12/// A parsed ref log line.
6#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]13#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
7#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]14#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
8#[non_exhaustive]15#[non_exhaustive]
9pub struct Line<'a> {16pub struct LineRef<'a> {
10 /// The previous object id in hexadecimal. Use [`Line::previous_oid()`] to get a more usable form.17 /// The previous object id in hexadecimal. Use [`LineRef::previous_oid()`] to get a more usable form.
11 pub previous_oid: &'a BStr,18 pub previous_oid: &'a BStr,
12 /// The new object id in hexadecimal. Use [`Line::new_oid()`] to get a more usable form.19 /// The new object id in hexadecimal. Use [`LineRef::new_oid()`] to get a more usable form.
13 pub new_oid: &'a BStr,20 pub new_oid: &'a BStr,
14 /// The signature of the currently configured committer.21 /// The signature of the currently configured committer.
15 #[cfg_attr(feature = "serde1", serde(borrow))]22 #[cfg_attr(feature = "serde1", serde(borrow))]
@@ -18,87 +25,16 @@ pub struct Line<'a> { · 2 unmodified lines
18 pub message: &'a BStr,25 pub message: &'a BStr,
19}26}
20 27
21///28/// A parsed ref log line that can be changed
22pub mod mutable {29#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
23 use bstr::BString;30#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
24 use git_hash::ObjectId;31pub struct Line {
25 32 /// The previous object id. Can be a null-sha to indicate this is a line for a new ref.
26 /// A parsed ref log line that can be changed33 pub previous_oid: ObjectId,
27 #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]34 /// The new object id. Can be a null-sha to indicate this ref is being deleted.
28 #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]35 pub new_oid: ObjectId,
29 pub struct Line {36 /// The signature of the currently configured committer.
30 /// The previous object id. Can be a null-sha to indicate this is a line for a new ref.37 pub signature: git_actor::Signature,
31 pub previous_oid: ObjectId,38 /// The message providing details about the operation performed in this log line.
32 /// The new object id. Can be a null-sha to indicate this ref is being deleted.39 pub message: BString,
33 pub new_oid: ObjectId,
34 /// The signature of the currently configured committer.
35 pub signature: git_actor::Signature,
36 /// The message providing details about the operation performed in this log line.
37 pub message: BString,
38 }
39
40 impl<'a> From<super::Line<'a>> for Line {
41 fn from(v: super::Line<'a>) -> Self {
42 Line {
43 previous_oid: v.previous_oid(),
44 new_oid: v.new_oid(),
45 signature: v.signature.into(),
46 message: v.message.into(),
47 }
48 }
49 }
50
51 impl<'a> super::Line<'a> {
52 /// Convert this instance into its mutable counterpart
53 pub fn to_mutable(&self) -> Line {
54 self.clone().into()
55 }
56 }
57
58 mod write {
59 use std::io;
60
61 use bstr::{BStr, ByteSlice};
62 use quick_error::quick_error;
63
64 use super::Line;
65
66 quick_error! {
67 /// The Error produced by [`Line::write_to()`] (but wrapped in an io error).
68 #[derive(Debug)]
69 #[allow(missing_docs)]
70 enum Error {
71 IllegalCharacter {
72 display("Messages must not contain newlines\\n")
73 }
74 }
75 }
76
77 impl From<Error> for io::Error {
78 fn from(err: Error) -> Self {
79 io::Error::new(io::ErrorKind::Other, err)
80 }
81 }
82
83 /// Output
84 impl Line {
85 /// Serialize this instance to `out` in the git serialization format for ref log lines.
86 pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> {
87 write!(out, "{} {} ", self.previous_oid, self.new_oid)?;
88 self.signature.write_to(&mut out)?;
89 writeln!(out, "\t{}", check_newlines(self.message.as_ref())?)
90 }
91 }
92
93 fn check_newlines(input: &BStr) -> Result<&BStr, Error> {
94 if input.find_byte(b'\n').is_some() {
95 return Err(Error::IllegalCharacter);
96 }
97 Ok(input)
98 }
99 }
100}40}
101
102///
103pub mod iter;
104mod line;
git-ref/src/store/file/loose/iter.rs+1−1
@@ -8,8 +8,8 @@ use git_features::fs::walkdir::DirEntryIter; · 7 unmodified lines
8use os_str_bytes::OsStrBytes;8use os_str_bytes::OsStrBytes;
9 9
10use crate::{10use crate::{
11 mutable::FullName,
12 store::file::{self, loose::Reference},11 store::file::{self, loose::Reference},
12 FullName,
13};13};
14 14
15/// An iterator over all valid loose reference paths as seen from a particular base directory.15/// An iterator over all valid loose reference paths as seen from a particular base directory.
git-ref/src/store/file/loose/mod.rs+3−3
@@ -1,12 +1,12 @@
1use crate::{mutable, Kind};1use crate::{FullName, Kind, Target};
2 2
3/// A git _ref_ which is stored in a file.3/// A git _ref_ which is stored in a file.
4#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Hash, Clone)]4#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Hash, Clone)]
5pub struct Reference {5pub struct Reference {
6 /// The path to uniquely identify this ref within its store.6 /// The path to uniquely identify this ref within its store.
7 pub name: mutable::FullName,7 pub name: FullName,
8 /// The target of the reference, either a symbolic reference by full name or an object by its id.8 /// The target of the reference, either a symbolic reference by full name or an object by its id.
9 pub target: mutable::Target,9 pub target: Target,
10}10}
11 11
12impl Reference {12impl Reference {
git-ref/src/store/file/loose/reference/decode.rs+8−10
@@ -11,9 +11,9 @@ use nom::{ · 10 unmodified lines
11use quick_error::quick_error;11use quick_error::quick_error;
12 12
13use crate::{13use crate::{
14 mutable,
15 parse::{hex_hash, newline},14 parse::{hex_hash, newline},
16 store::file::loose::Reference,15 store::file::loose::Reference,
16 FullName, Target,
17};17};
18 18
19enum MaybeUnsafeState {19enum MaybeUnsafeState {
@@ -36,18 +36,16 @@ quick_error! { · 16 unmodified lines
36 }36 }
37}37}
38 38
39impl TryFrom<MaybeUnsafeState> for mutable::Target {39impl TryFrom<MaybeUnsafeState> for Target {
40 type Error = Error;40 type Error = Error;
41 41
42 fn try_from(v: MaybeUnsafeState) -> Result<Self, Self::Error> {42 fn try_from(v: MaybeUnsafeState) -> Result<Self, Self::Error> {
43 Ok(match v {43 Ok(match v {
44 MaybeUnsafeState::Id(id) => mutable::Target::Peeled(id),44 MaybeUnsafeState::Id(id) => Target::Peeled(id),
45 MaybeUnsafeState::UnvalidatedPath(name) => {45 MaybeUnsafeState::UnvalidatedPath(name) => Target::Symbolic(match git_validate::refname(name.as_ref()) {
46 mutable::Target::Symbolic(match git_validate::refname(name.as_ref()) {46 Ok(_) => FullName(name),
47 Ok(_) => mutable::FullName(name),47 Err(err) => return Err(Error::RefnameValidation { err, path: name }),
48 Err(err) => return Err(Error::RefnameValidation { err, path: name }),48 }),
49 })
50 }
51 })49 })
52 }50 }
53}51}
@@ -55,7 +53,7 @@ impl TryFrom<MaybeUnsafeState> for mutable::Target { · 1 unmodified line
55impl Reference {53impl Reference {
56 /// Create a new reference of the given `parent` store with `relative_path` service as unique identifier54 /// Create a new reference of the given `parent` store with `relative_path` service as unique identifier
57 /// at which the `path_contents` was read to obtain the refs value.55 /// at which the `path_contents` was read to obtain the refs value.
58 pub fn try_from_path(name: mutable::FullName, path_contents: &[u8]) -> Result<Self, Error> {56 pub fn try_from_path(name: FullName, path_contents: &[u8]) -> Result<Self, Error> {
59 Ok(Reference {57 Ok(Reference {
60 name,58 name,
61 target: parse(path_contents)59 target: parse(path_contents)
git-ref/src/store/file/loose/reference/logiter.rs+4−4
@@ -18,7 +18,7 @@ impl Reference { · 17 unmodified lines
18 /// If the caller needs to know if it's readable, try to read the log instead with a reverse or forward iterator.18 /// If the caller needs to know if it's readable, try to read the log instead with a reverse or forward iterator.
19 pub fn log_exists(&self, store: &file::Store) -> bool {19 pub fn log_exists(&self, store: &file::Store) -> bool {
20 store20 store
21 .reflog_exists(self.name.borrow())21 .reflog_exists(self.name.to_ref())
22 .expect("name conversion infallible")22 .expect("name conversion infallible")
23 }23 }
24 /// Return a reflog reverse iterator for this ref, reading chunks from the back into the fixed buffer `buf`, in the given `store`.24 /// Return a reflog reverse iterator for this ref, reading chunks from the back into the fixed buffer `buf`, in the given `store`.
@@ -30,7 +30,7 @@ impl Reference { · 5 unmodified lines
30 store: &file::Store,30 store: &file::Store,
31 buf: &'b mut [u8],31 buf: &'b mut [u8],
32 ) -> std::io::Result<Option<log::iter::Reverse<'b, std::fs::File>>> {32 ) -> std::io::Result<Option<log::iter::Reverse<'b, std::fs::File>>> {
33 store.reflog_iter_rev(self.name.borrow(), buf).map_err(must_be_io_err)33 store.reflog_iter_rev(self.name.to_ref(), buf).map_err(must_be_io_err)
34 }34 }
35 35
36 /// Return a reflog forward iterator for this ref and write its file contents into `buf`, in the given `store`.36 /// Return a reflog forward iterator for this ref and write its file contents into `buf`, in the given `store`.
@@ -41,7 +41,7 @@ impl Reference { · 4 unmodified lines
41 &'a self,41 &'a self,
42 store: &file::Store,42 store: &file::Store,
43 buf: &'b mut Vec<u8>,43 buf: &'b mut Vec<u8>,
44 ) -> std::io::Result<Option<impl Iterator<Item = Result<log::Line<'b>, log::iter::decode::Error>> + 'a>> {44 ) -> std::io::Result<Option<impl Iterator<Item = Result<log::LineRef<'b>, log::iter::decode::Error>> + 'a>> {
45 store.reflog_iter(self.name.borrow(), buf).map_err(must_be_io_err)45 store.reflog_iter(self.name.to_ref(), buf).map_err(must_be_io_err)
46 }46 }
47}47}
git-ref/src/store/file/loose/reference/peel.rs+2−2
@@ -2,11 +2,11 @@ use quick_error::quick_error; · 1 unmodified line
2 2
3use crate::{3use crate::{
4 file,4 file,
5 mutable::Target,
6 store::{5 store::{
7 file::{find, loose},6 file::{find, loose},
8 packed,7 packed,
9 },8 },
9 Target,
10};10};
11 11
12quick_error! {12quick_error! {
@@ -67,8 +67,8 @@ pub mod to_id { · 54 unmodified lines
67 use quick_error::quick_error;67 use quick_error::quick_error;
68 68
69 use crate::{69 use crate::{
70 mutable::{FullName, Target},
71 store::{file, file::loose, packed},70 store::{file, file::loose, packed},
71 FullName, Target,
72 };72 };
73 73
74 quick_error! {74 quick_error! {
git-ref/src/store/file/loose/reflog.rs+8−8
@@ -2,7 +2,7 @@ use std::{convert::TryInto, io::Read, path::PathBuf}; · 1 unmodified line
2 2
3use crate::{3use crate::{
4 store::{file, file::log},4 store::{file, file::log},
5 FullName,5 FullNameRef,
6};6};
7 7
8impl file::Store {8impl file::Store {
@@ -13,7 +13,7 @@ impl file::Store { · 4 unmodified lines
13 /// If the caller needs to know if it's readable, try to read the log instead with a reverse or forward iterator.13 /// If the caller needs to know if it's readable, try to read the log instead with a reverse or forward iterator.
14 pub fn reflog_exists<'a, Name, E>(&self, name: Name) -> Result<bool, E>14 pub fn reflog_exists<'a, Name, E>(&self, name: Name) -> Result<bool, E>
15 where15 where
16 Name: TryInto<FullName<'a>, Error = E>,16 Name: TryInto<FullNameRef<'a>, Error = E>,
17 crate::name::Error: From<E>,17 crate::name::Error: From<E>,
18 {18 {
19 Ok(self.reflog_path(name.try_into()?).is_file())19 Ok(self.reflog_path(name.try_into()?).is_file())
@@ -29,10 +29,10 @@ impl file::Store { · 9 unmodified lines
29 buf: &'b mut [u8],29 buf: &'b mut [u8],
30 ) -> Result<Option<log::iter::Reverse<'b, std::fs::File>>, Error>30 ) -> Result<Option<log::iter::Reverse<'b, std::fs::File>>, Error>
31 where31 where
32 Name: TryInto<FullName<'a>, Error = E>,32 Name: TryInto<FullNameRef<'a>, Error = E>,
33 crate::name::Error: From<E>,33 crate::name::Error: From<E>,
34 {34 {
35 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;35 let name: FullNameRef<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;
36 let path = self.reflog_path(name);36 let path = self.reflog_path(name);
37 if path.is_dir() {37 if path.is_dir() {
38 return Ok(None);38 return Ok(None);
@@ -52,12 +52,12 @@ impl file::Store { · 13 unmodified lines
52 &self,52 &self,
53 name: Name,53 name: Name,
54 buf: &'b mut Vec<u8>,54 buf: &'b mut Vec<u8>,
55 ) -> Result<Option<impl Iterator<Item = Result<log::Line<'b>, log::iter::decode::Error>>>, Error>55 ) -> Result<Option<impl Iterator<Item = Result<log::LineRef<'b>, log::iter::decode::Error>>>, Error>
56 where56 where
57 Name: TryInto<FullName<'a>, Error = E>,57 Name: TryInto<FullNameRef<'a>, Error = E>,
58 crate::name::Error: From<E>,58 crate::name::Error: From<E>,
59 {59 {
60 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;60 let name: FullNameRef<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;
61 let path = self.reflog_path(name);61 let path = self.reflog_path(name);
62 match std::fs::File::open(&path) {62 match std::fs::File::open(&path) {
63 Ok(mut file) => {63 Ok(mut file) => {
@@ -77,7 +77,7 @@ impl file::Store { · 13 unmodified lines
77 77
78impl file::Store {78impl file::Store {
79 /// Implements the logic required to transform a fully qualified refname into its log name79 /// Implements the logic required to transform a fully qualified refname into its log name
80 pub(crate) fn reflog_path(&self, name: FullName<'_>) -> PathBuf {80 pub(crate) fn reflog_path(&self, name: FullNameRef<'_>) -> PathBuf {
81 self.reflog_path_inner(&name.to_path())81 self.reflog_path_inner(&name.to_path())
82 }82 }
83}83}
git-ref/src/store/file/loose/reflog/create_or_update/tests.rs+6−6
@@ -1,5 +1,5 @@
1use super::*;1use super::*;
2use crate::{file::WriteReflog, store::file::log, FullName};2use crate::{file::WriteReflog, store::file::log, FullNameRef};
3use bstr::ByteSlice;3use bstr::ByteSlice;
4use git_actor::{Sign, Signature, Time};4use git_actor::{Sign, Signature, Time};
5use git_lock::acquire::Fail;5use git_lock::acquire::Fail;
@@ -16,7 +16,7 @@ fn empty_store(writemode: WriteReflog) -> Result<(TempDir, file::Store)> { · 10 unmodified lines
16}16}
17 17
18fn reflock(store: &file::Store, full_name: &str) -> Result<git_lock::Marker> {18fn reflock(store: &file::Store, full_name: &str) -> Result<git_lock::Marker> {
19 let full_name: FullName<'_> = full_name.try_into()?;19 let full_name: FullNameRef<'_> = full_name.try_into()?;
20 git_lock::Marker::acquire_to_hold_resource(20 git_lock::Marker::acquire_to_hold_resource(
21 store.reference_path(&full_name.to_path()),21 store.reference_path(&full_name.to_path()),
22 Fail::Immediately,22 Fail::Immediately,
@@ -25,11 +25,11 @@ fn reflock(store: &file::Store, full_name: &str) -> Result<git_lock::Marker> { · 2 unmodified lines
25 .map_err(Into::into)25 .map_err(Into::into)
26}26}
27 27
28fn reflog_lines(store: &file::Store, name: &str, buf: &mut Vec<u8>) -> Result<Vec<log::mutable::Line>> {28fn reflog_lines(store: &file::Store, name: &str, buf: &mut Vec<u8>) -> Result<Vec<log::Line>> {
29 store29 store
30 .reflog_iter(name, buf)?30 .reflog_iter(name, buf)?
31 .expect("existing reflog")31 .expect("existing reflog")
32 .map(|l| l.map(log::mutable::Line::from))32 .map(|l| l.map(log::Line::from))
33 .collect::<std::result::Result<Vec<_>, _>>()33 .collect::<std::result::Result<Vec<_>, _>>()
34 .map_err(Into::into)34 .map_err(Into::into)
35}35}
@@ -83,7 +83,7 @@ fn missing_reflog_creates_it_even_if_similarly_named_empty_dir_exists_and_append · 47 unmodified lines
83 WriteReflog::Normal => {83 WriteReflog::Normal => {
84 assert_eq!(84 assert_eq!(
85 reflog_lines(&store, full_name, &mut buf)?,85 reflog_lines(&store, full_name, &mut buf)?,
86 vec![log::mutable::Line {86 vec![log::Line {
87 previous_oid: ObjectId::null_sha1(),87 previous_oid: ObjectId::null_sha1(),
88 new_oid: new,88 new_oid: new,
89 signature: committer.clone(),89 signature: committer.clone(),
@@ -104,7 +104,7 @@ fn missing_reflog_creates_it_even_if_similarly_named_empty_dir_exists_and_append · 14 unmodified lines
104 assert_eq!(lines.len(), 2, "now there is another line");104 assert_eq!(lines.len(), 2, "now there is another line");
105 assert_eq!(105 assert_eq!(
106 lines.last().expect("non-empty"),106 lines.last().expect("non-empty"),
107 &log::mutable::Line {107 &log::Line {
108 previous_oid: previous,108 previous_oid: previous,
109 new_oid: new,109 new_oid: new,
110 signature: committer.clone(),110 signature: committer.clone(),
git-ref/src/store/file/overlay.rs+1−1
@@ -7,8 +7,8 @@ use std::{ · 6 unmodified lines
7 7
8use crate::{8use crate::{
9 file::{loose, path_to_name, Reference},9 file::{loose, path_to_name, Reference},
10 mutable::FullName,
11 store::{file, packed},10 store::{file, packed},
11 FullName,
12};12};
13 13
14/// An iterator stepping through sorted input of loose references and packed references, preferring loose refs over otherwise14/// An iterator stepping through sorted input of loose references and packed references, preferring loose refs over otherwise
git-ref/src/store/file/reference.rs+12−13
@@ -5,13 +5,12 @@ use git_hash::ObjectId; · 4 unmodified lines
5 5
6use crate::{6use crate::{
7 file::loose::reference::logiter::must_be_io_err,7 file::loose::reference::logiter::must_be_io_err,
8 mutable,
9 store::{8 store::{
10 file,9 file,
11 file::{log, loose},10 file::{log, loose},
12 packed,11 packed,
13 },12 },
14 FullName, Namespace,13 FullNameRef, Namespace, Target,
15};14};
16 15
17/// Either a loose or packed reference, depending on where it was found.16/// Either a loose or packed reference, depending on where it was found.
@@ -82,7 +81,7 @@ impl<'p> Reference<'p> { · 64 unmodified lines
82 match self {81 match self {
83 Reference::Loose(r) => r.follow_symbolic(store, packed),82 Reference::Loose(r) => r.follow_symbolic(store, packed),
84 Reference::Packed(p) => packed83 Reference::Packed(p) => packed
85 .and_then(|packed| packed.find(p.name).ok().flatten()) // needed to get data with 'p2 lifetime84 .and_then(|packed| packed.try_find(p.name).ok().flatten()) // needed to get data with 'p2 lifetime
86 .and_then(|np| {85 .and_then(|np| {
87 p.object.and(np.object).map(|peeled| {86 p.object.and(np.object).map(|peeled| {
88 Ok(Reference::Packed(packed::Reference {87 Ok(Reference::Packed(packed::Reference {
@@ -112,9 +111,9 @@ impl<'p> Reference<'p> { · 23 unmodified lines
112 &'a self,111 &'a self,
113 store: &file::Store,112 store: &file::Store,
114 buf: &'b mut Vec<u8>,113 buf: &'b mut Vec<u8>,
115 ) -> std::io::Result<Option<impl Iterator<Item = Result<log::Line<'b>, log::iter::decode::Error>> + 'a>> {114 ) -> std::io::Result<Option<impl Iterator<Item = Result<log::LineRef<'b>, log::iter::decode::Error>> + 'a>> {
116 match self {115 match self {
117 Reference::Loose(r) => store.reflog_iter(r.name.borrow(), buf).map_err(must_be_io_err),116 Reference::Loose(r) => store.reflog_iter(r.name.to_ref(), buf).map_err(must_be_io_err),
118 Reference::Packed(p) => store.reflog_iter(p.name, buf).map_err(must_be_io_err),117 Reference::Packed(p) => store.reflog_iter(p.name, buf).map_err(must_be_io_err),
119 }118 }
120 }119 }
@@ -128,9 +127,9 @@ impl<'p> Reference<'p> { · 7 unmodified lines
128 }127 }
129 128
130 /// Transform this reference into an owned `Target`129 /// Transform this reference into an owned `Target`
131 pub fn into_target(self) -> mutable::Target {130 pub fn into_target(self) -> Target {
132 match self {131 match self {
133 Reference::Packed(p) => mutable::Target::Peeled(p.object()),132 Reference::Packed(p) => Target::Peeled(p.object()),
134 Reference::Loose(r) => r.target,133 Reference::Loose(r) => r.target,
135 }134 }
136 }135 }
@@ -144,28 +143,28 @@ impl<'p> Reference<'p> { · 7 unmodified lines
144 }143 }
145 144
146 /// Return the full validated name of the reference, which may include a namespace.145 /// Return the full validated name of the reference, which may include a namespace.
147 pub fn name(&self) -> FullName<'_> {146 pub fn name(&self) -> FullNameRef<'_> {
148 match self {147 match self {
149 Reference::Packed(p) => p.name,148 Reference::Packed(p) => p.name,
150 Reference::Loose(l) => l.name.borrow(),149 Reference::Loose(l) => l.name.to_ref(),
151 }150 }
152 }151 }
153 152
154 /// Return the full validated name of the reference, with the given namespace stripped if possible.153 /// Return the full validated name of the reference, with the given namespace stripped if possible.
155 ///154 ///
156 /// If the reference name wasn't prefixed with `namespace`, `None` is returned instead.155 /// If the reference name wasn't prefixed with `namespace`, `None` is returned instead.
157 pub fn name_without_namespace(&self, namespace: &Namespace) -> Option<FullName<'_>> {156 pub fn name_without_namespace(&self, namespace: &Namespace) -> Option<FullNameRef<'_>> {
158 self.name()157 self.name()
159 .0158 .0
160 .as_bstr()159 .as_bstr()
161 .strip_prefix(namespace.0.as_bstr().as_ref())160 .strip_prefix(namespace.0.as_bstr().as_ref())
162 .map(|stripped| FullName(stripped.as_bstr()))161 .map(|stripped| FullNameRef(stripped.as_bstr()))
163 }162 }
164 163
165 /// Return the target to which the reference points to.164 /// Return the target to which the reference points to.
166 pub fn target(&self) -> mutable::Target {165 pub fn target(&self) -> Target {
167 match self {166 match self {
168 Reference::Packed(p) => mutable::Target::Peeled(p.target()),167 Reference::Packed(p) => Target::Peeled(p.target()),
169 Reference::Loose(l) => l.target.clone(),168 Reference::Loose(l) => l.target.clone(),
170 }169 }
171 }170 }
git-ref/src/store/file/transaction/commit.rs+2−2
@@ -1,7 +1,7 @@
1use crate::{1use crate::{
2 mutable::Target,
3 store::file::{transaction::PackedRefs, Transaction},2 store::file::{transaction::PackedRefs, Transaction},
4 transaction::{Change, LogChange, RefEdit, RefLog},3 transaction::{Change, LogChange, RefEdit, RefLog},
4 Target,
5};5};
6 6
7impl<'s> Transaction<'s> {7impl<'s> Transaction<'s> {
@@ -102,7 +102,7 @@ impl<'s> Transaction<'s> { · 94 unmodified lines
102 Change::Delete { .. } => {102 Change::Delete { .. } => {
103 // Reflog deletion happens first in case it fails a ref without log is less terrible than103 // Reflog deletion happens first in case it fails a ref without log is less terrible than
104 // a log without a reference.104 // a log without a reference.
105 let reflog_path = self.store.reflog_path(change.update.name.borrow());105 let reflog_path = self.store.reflog_path(change.update.name.to_ref());
106 if let Err(err) = std::fs::remove_file(&reflog_path) {106 if let Err(err) = std::fs::remove_file(&reflog_path) {
107 if err.kind() != std::io::ErrorKind::NotFound {107 if err.kind() != std::io::ErrorKind::NotFound {
108 return Err(Error::DeleteReflog {108 return Err(Error::DeleteReflog {
git-ref/src/store/file/transaction/prepare.rs+6−6
@@ -1,5 +1,4 @@
1use crate::{1use crate::{
2 mutable::Target,
3 packed,2 packed,
4 store::{3 store::{
5 file,4 file,
@@ -10,6 +9,7 @@ use crate::{ · 4 unmodified lines
10 },9 },
11 },10 },
12 transaction::{Change, Create, LogChange, RefEdit, RefEditsExt, RefLog},11 transaction::{Change, Create, LogChange, RefEdit, RefEditsExt, RefLog},
12 Target,
13};13};
14 14
15impl<'s> Transaction<'s> {15impl<'s> Transaction<'s> {
@@ -44,7 +44,7 @@ impl<'s> Transaction<'s> { · 28 unmodified lines
44 })44 })
45 .and_then(|maybe_loose| match (maybe_loose, packed) {45 .and_then(|maybe_loose| match (maybe_loose, packed) {
46 (None, Some(packed)) => packed46 (None, Some(packed)) => packed
47 .find(change.update.name.borrow())47 .try_find(change.update.name.to_ref())
48 .map(|opt| opt.map(file::Reference::Packed))48 .map(|opt| opt.map(file::Reference::Packed))
49 .map_err(Error::from),49 .map_err(Error::from),
50 (None, None) => Ok(None),50 (None, None) => Ok(None),
@@ -104,7 +104,7 @@ impl<'s> Transaction<'s> { · 53 unmodified lines
104 104
105 let existing_ref = existing_ref?;105 let existing_ref = existing_ref?;
106 match (&previous, &existing_ref) {106 match (&previous, &existing_ref) {
107 (Create::Only, Some(existing)) if existing.target() != new.borrow() => {107 (Create::Only, Some(existing)) if existing.target() != new.to_ref() => {
108 let new = new.clone();108 let new = new.clone();
109 return Err(Error::MustNotExist {109 return Err(Error::MustNotExist {
110 full_name: change.name(),110 full_name: change.name(),
@@ -191,7 +191,7 @@ impl<'s> Transaction<'s> { · 80 unmodified lines
191 |name| {191 |name| {
192 let symbolic_refs_are_never_packed = None;192 let symbolic_refs_are_never_packed = None;
193 store193 store
194 .find_existing(name, symbolic_refs_are_never_packed)194 .find(name, symbolic_refs_are_never_packed)
195 .map(|r| r.into_target())195 .map(|r| r.into_target())
196 .ok()196 .ok()
197 },197 },
@@ -321,7 +321,7 @@ impl<'s> Transaction<'s> { · 123 unmodified lines
321 321
322 // traverse parent chain from leaf/peeled ref and set the leaf previous oid accordingly322 // traverse parent chain from leaf/peeled ref and set the leaf previous oid accordingly
323 // to help with their reflog entries323 // to help with their reflog entries
324 if let (Some(crate::Target::Peeled(oid)), Some(parent_idx)) =324 if let (Some(crate::TargetRef::Peeled(oid)), Some(parent_idx)) =
325 (change.update.change.previous_value(), change.parent_index)325 (change.update.change.previous_value(), change.parent_index)
326 {326 {
327 let oid = oid.to_owned();327 let oid = oid.to_owned();
@@ -342,8 +342,8 @@ mod error { · 14 unmodified lines
342 use quick_error::quick_error;342 use quick_error::quick_error;
343 343
344 use crate::{344 use crate::{
345 mutable::Target,
346 store::{file, packed},345 store::{file, packed},
346 Target,
347 };347 };
348 348
349 quick_error! {349 quick_error! {
git-ref/src/store/packed/decode.rs+1−1
@@ -73,7 +73,7 @@ pub fn reference<'a, E: ParseError<&'a [u8]> + FromExternalError<&'a [u8], crate · 72 unmodified lines
73) -> IResult<&'a [u8], packed::Reference<'a>, E> {73) -> IResult<&'a [u8], packed::Reference<'a>, E> {
74 let (input, (target, name)) = tuple((74 let (input, (target, name)) = tuple((
75 terminated(hex_hash, tag(b" ")),75 terminated(hex_hash, tag(b" ")),
76 map_res(until_newline, crate::FullName::try_from),76 map_res(until_newline, crate::FullNameRef::try_from),
77 ))(input)?;77 ))(input)?;
78 let (rest, object) = opt(delimited(tag(b"^"), hex_hash, newline))(input)?;78 let (rest, object) = opt(delimited(tag(b"^"), hex_hash, newline))(input)?;
79 Ok((rest, packed::Reference { name, target, object }))79 Ok((rest, packed::Reference { name, target, object }))
git-ref/src/store/packed/decode/tests.rs+3−3
@@ -7,7 +7,7 @@ mod reference { · 6 unmodified lines
7 use super::Result;7 use super::Result;
8 use crate::{8 use crate::{
9 store::{packed, packed::decode},9 store::{packed, packed::decode},
10 FullName,10 FullNameRef,
11 };11 };
12 12
13 #[test]13 #[test]
@@ -28,7 +28,7 @@ mod reference { · 14 unmodified lines
28 assert_eq!(28 assert_eq!(
29 parsed,29 parsed,
30 packed::Reference {30 packed::Reference {
31 name: FullName("refs/heads/alternates-after-packs-and-loose".into()),31 name: FullNameRef("refs/heads/alternates-after-packs-and-loose".into()),
32 target: "d53c4b0f91f1b29769c9430f2d1c0bcab1170c75".into(),32 target: "d53c4b0f91f1b29769c9430f2d1c0bcab1170c75".into(),
33 object: Some("e9cdc958e7ce2290e2d7958cdb5aa9323ef35d37".into())33 object: Some("e9cdc958e7ce2290e2d7958cdb5aa9323ef35d37".into())
34 }34 }
@@ -38,7 +38,7 @@ mod reference { · 3 unmodified lines
38 38
39 let (input, parsed) = decode::reference::<VerboseError<_>>(input)?;39 let (input, parsed) = decode::reference::<VerboseError<_>>(input)?;
40 assert!(input.is_empty(), "exhausted");40 assert!(input.is_empty(), "exhausted");
41 assert_eq!(parsed.name, FullName("refs/heads/avoid-double-lookup".into()));41 assert_eq!(parsed.name, FullNameRef("refs/heads/avoid-double-lookup".into()));
42 assert_eq!(parsed.target, "eaae9c1bc723209d793eb93f5587fa2604d5cd92");42 assert_eq!(parsed.target, "eaae9c1bc723209d793eb93f5587fa2604d5cd92");
43 assert!(parsed.object.is_none());43 assert!(parsed.object.is_none());
44 Ok(())44 Ok(())
git-ref/src/store/packed/find.rs+6−6
@@ -2,14 +2,14 @@ use std::{borrow::Cow, convert::TryInto}; · 1 unmodified line
2 2
3use bstr::{BStr, BString, ByteSlice};3use bstr::{BStr, BString, ByteSlice};
4 4
5use crate::{store::packed, PartialName};5use crate::{store::packed, PartialNameRef};
6 6
7/// packed-refs specific functionality7/// packed-refs specific functionality
8impl packed::Buffer {8impl packed::Buffer {
9 /// Find a reference with the given `name` and return it.9 /// Find a reference with the given `name` and return it.
10 pub fn find<'a, Name, E>(&self, name: Name) -> Result<Option<packed::Reference<'_>>, Error>10 pub fn try_find<'a, Name, E>(&self, name: Name) -> Result<Option<packed::Reference<'_>>, Error>
11 where11 where
12 Name: TryInto<PartialName<'a>, Error = E>,12 Name: TryInto<PartialNameRef<'a>, Error = E>,
13 Error: From<E>,13 Error: From<E>,
14 {14 {
15 let name = name.try_into()?;15 let name = name.try_into()?;
@@ -52,12 +52,12 @@ impl packed::Buffer { · 36 unmodified lines
52 }52 }
53 53
54 /// Find a reference with the given `name` and return it.54 /// Find a reference with the given `name` and return it.
55 pub fn find_existing<'a, Name, E>(&self, name: Name) -> Result<packed::Reference<'_>, existing::Error>55 pub fn find<'a, Name, E>(&self, name: Name) -> Result<packed::Reference<'_>, existing::Error>
56 where56 where
57 Name: TryInto<PartialName<'a>, Error = E>,57 Name: TryInto<PartialNameRef<'a>, Error = E>,
58 Error: From<E>,58 Error: From<E>,
59 {59 {
60 match self.find(name) {60 match self.try_find(name) {
61 Ok(Some(r)) => Ok(r),61 Ok(Some(r)) => Ok(r),
62 Ok(None) => Err(existing::Error::NotFound),62 Ok(None) => Err(existing::Error::NotFound),
63 Err(err) => Err(existing::Error::Find(err)),63 Err(err) => Err(existing::Error::Find(err)),
git-ref/src/store/packed/mod.rs+2−2
@@ -4,7 +4,7 @@ use bstr::{BStr, BString}; · 3 unmodified lines
4use filebuffer::FileBuffer;4use filebuffer::FileBuffer;
5use git_hash::ObjectId;5use git_hash::ObjectId;
6 6
7use crate::{transaction::RefEdit, FullName};7use crate::{transaction::RefEdit, FullNameRef};
8 8
9enum Backing {9enum Backing {
10 /// The buffer is loaded entirely in memory, along with the `offset` to the first record past the header.10 /// The buffer is loaded entirely in memory, along with the `offset` to the first record past the header.
@@ -42,7 +42,7 @@ pub(crate) struct Transaction { · 31 unmodified lines
42#[derive(Debug, PartialEq, Eq)]42#[derive(Debug, PartialEq, Eq)]
43pub struct Reference<'a> {43pub struct Reference<'a> {
44 /// The validated full name of the reference.44 /// The validated full name of the reference.
45 pub name: FullName<'a>,45 pub name: FullNameRef<'a>,
46 /// The target object id of the reference, hex encoded.46 /// The target object id of the reference, hex encoded.
47 pub target: &'a BStr,47 pub target: &'a BStr,
48 /// The fully peeled object id, hex encoded, that the ref is ultimately pointing to48 /// The fully peeled object id, hex encoded, that the ref is ultimately pointing to
git-ref/src/store/packed/transaction.rs+2−4
@@ -1,9 +1,9 @@
1use std::io::Write;1use std::io::Write;
2 2
3use crate::{3use crate::{
4 mutable::Target,
5 store::{file::transaction::FindObjectFn, packed, packed::Edit},4 store::{file::transaction::FindObjectFn, packed, packed::Edit},
6 transaction::{Change, RefEdit},5 transaction::{Change, RefEdit},
6 Target,
7};7};
8 8
9pub(crate) const HEADER_LINE: &[u8] = b"# pack-refs with: peeled fully-peeled sorted \n";9pub(crate) const HEADER_LINE: &[u8] = b"# pack-refs with: peeled fully-peeled sorted \n";
@@ -54,9 +54,7 @@ impl packed::Transaction { · 44 unmodified lines
54 .into_iter()54 .into_iter()
55 .filter(|edit| {55 .filter(|edit| {
56 if let Change::Delete { .. } = edit.change {56 if let Change::Delete { .. } = edit.change {
57 buffer57 buffer.as_ref().map_or(true, |b| b.find(edit.name.to_ref()).is_ok())
58 .as_ref()
59 .map_or(true, |b| b.find_existing(edit.name.borrow()).is_ok())
60 } else {58 } else {
61 true59 true
62 }60 }
git-ref/src/target.rs+83−8
@@ -1,9 +1,38 @@
1use bstr::BStr;1use bstr::{BStr, ByteSlice};
2use git_hash::oid;2use git_hash::{oid, ObjectId};
3use std::fmt;
3 4
4use crate::{Kind, Target};5use crate::{FullName, Kind, Target, TargetRef};
5 6
6impl<'a> Target<'a> {7impl<'a> TargetRef<'a> {
8 /// Returns the kind of the target the ref is pointing to.
9 pub fn kind(&self) -> Kind {
10 match self {
11 TargetRef::Symbolic(_) => Kind::Symbolic,
12 TargetRef::Peeled(_) => Kind::Peeled,
13 }
14 }
15 /// Interpret this target as object id which maybe `None` if it is symbolic.
16 pub fn as_id(&self) -> Option<&oid> {
17 match self {
18 TargetRef::Symbolic(_) => None,
19 TargetRef::Peeled(oid) => Some(oid),
20 }
21 }
22 /// Interpret this target as name of the reference it points to which maybe `None` if it an object id.
23 pub fn as_name(&self) -> Option<&BStr> {
24 match self {
25 TargetRef::Symbolic(path) => Some(path),
26 TargetRef::Peeled(_) => None,
27 }
28 }
29 /// Convert this instance into an owned version, without consuming it.
30 pub fn into_owned(self) -> crate::Target {
31 self.into()
32 }
33}
34
35impl Target {
7 /// Returns the kind of the target the ref is pointing to.36 /// Returns the kind of the target the ref is pointing to.
8 pub fn kind(&self) -> Kind {37 pub fn kind(&self) -> Kind {
9 match self {38 match self {
@@ -11,6 +40,23 @@ impl<'a> Target<'a> { · 1 unmodified line
11 Target::Peeled(_) => Kind::Peeled,40 Target::Peeled(_) => Kind::Peeled,
12 }41 }
13 }42 }
43
44 /// Return true if this is a peeled target with a null hash
45 pub fn is_null(&self) -> bool {
46 match self {
47 Target::Peeled(oid) => oid.is_null(),
48 Target::Symbolic(_) => false,
49 }
50 }
51
52 /// Interpret this owned Target as shared Target
53 pub fn to_ref(&self) -> crate::TargetRef<'_> {
54 match self {
55 Target::Peeled(oid) => crate::TargetRef::Peeled(oid),
56 Target::Symbolic(name) => crate::TargetRef::Symbolic(name.0.as_bstr()),
57 }
58 }
59
14 /// Interpret this target as object id which maybe `None` if it is symbolic.60 /// Interpret this target as object id which maybe `None` if it is symbolic.
15 pub fn as_id(&self) -> Option<&oid> {61 pub fn as_id(&self) -> Option<&oid> {
16 match self {62 match self {
@@ -21,12 +67,41 @@ impl<'a> Target<'a> { · 4 unmodified lines
21 /// Interpret this target as name of the reference it points to which maybe `None` if it an object id.67 /// Interpret this target as name of the reference it points to which maybe `None` if it an object id.
22 pub fn as_name(&self) -> Option<&BStr> {68 pub fn as_name(&self) -> Option<&BStr> {
23 match self {69 match self {
24 Target::Symbolic(path) => Some(path),70 Target::Symbolic(name) => Some(name.as_bstr()),
25 Target::Peeled(_) => None,71 Target::Peeled(_) => None,
26 }72 }
27 }73 }
28 /// Convert this instance into an owned version, without consuming it.74
29 pub fn to_owned(self) -> crate::mutable::Target {75 /// Create an instance that signals that a reference should exist if this value is used in a [`Change`][crate::transaction::Change].
30 self.into()76 pub fn must_exist() -> Self {
77 Target::Peeled(ObjectId::null_sha1())
78 }
79}
80
81impl<'a> From<crate::TargetRef<'a>> for Target {
82 fn from(src: crate::TargetRef<'a>) -> Self {
83 match src {
84 crate::TargetRef::Peeled(oid) => Target::Peeled(oid.to_owned()),
85 crate::TargetRef::Symbolic(name) => Target::Symbolic(FullName(name.to_owned())),
86 }
87 }
88}
89
90impl<'a> PartialEq<crate::TargetRef<'a>> for Target {
91 fn eq(&self, other: &crate::TargetRef<'a>) -> bool {
92 match (self, other) {
93 (Target::Peeled(lhs), crate::TargetRef::Peeled(rhs)) => lhs == rhs,
94 (Target::Symbolic(lhs), crate::TargetRef::Symbolic(rhs)) => lhs.as_bstr() == *rhs,
95 _ => false,
96 }
97 }
98}
99
100impl fmt::Display for Target {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 match self {
103 Target::Peeled(oid) => oid.fmt(f),
104 Target::Symbolic(name) => write!(f, "ref: {}", name.as_bstr()),
105 }
31 }106 }
32}107}
git-ref/src/transaction.rs+7−7
@@ -15,7 +15,7 @@ · 14 unmodified lines
15use bstr::BString;15use bstr::BString;
16use git_hash::ObjectId;16use git_hash::ObjectId;
17 17
18use crate::mutable::{FullName, Target};18use crate::{FullName, Target};
19 19
20/// A change to the reflog.20/// A change to the reflog.
21#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]21#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
@@ -101,14 +101,14 @@ pub enum Change { · 79 unmodified lines
101 101
102impl Change {102impl Change {
103 /// Return references to values that are in common between all variants.103 /// Return references to values that are in common between all variants.
104 pub fn previous_value(&self) -> Option<crate::Target<'_>> {104 pub fn previous_value(&self) -> Option<crate::TargetRef<'_>> {
105 match self {105 match self {
106 Change::Update { mode: Create::Only, .. } => None,106 Change::Update { mode: Create::Only, .. } => None,
107 Change::Update {107 Change::Update {
108 mode: Create::OrUpdate { previous },108 mode: Create::OrUpdate { previous },
109 ..109 ..
110 }110 }
111 | Change::Delete { previous, .. } => previous.as_ref().map(|t| t.borrow()),111 | Change::Delete { previous, .. } => previous.as_ref().map(|t| t.to_ref()),
112 }112 }
113 }113 }
114}114}
@@ -139,7 +139,7 @@ mod ext { · 24 unmodified lines
139 139
140 use crate::{140 use crate::{
141 transaction::{Change, LogChange, RefEdit, RefLog, Target},141 transaction::{Change, LogChange, RefEdit, RefLog, Target},
142 Namespace, PartialName,142 Namespace, PartialNameRef,
143 };143 };
144 144
145 /// An extension trait to perform commonly used operations on edits across different ref stores.145 /// An extension trait to perform commonly used operations on edits across different ref stores.
@@ -155,7 +155,7 @@ mod ext { · 9 unmodified lines
155 /// Note no action is performed if deref isn't specified.155 /// Note no action is performed if deref isn't specified.
156 fn extend_with_splits_of_symbolic_refs(156 fn extend_with_splits_of_symbolic_refs(
157 &mut self,157 &mut self,
158 find: impl FnMut(PartialName<'_>) -> Option<Target>,158 find: impl FnMut(PartialNameRef<'_>) -> Option<Target>,
159 make_entry: impl FnMut(usize, RefEdit) -> T,159 make_entry: impl FnMut(usize, RefEdit) -> T,
160 ) -> Result<(), std::io::Error>;160 ) -> Result<(), std::io::Error>;
161 161
@@ -168,7 +168,7 @@ mod ext { · 6 unmodified lines
168 /// Users call this to assure derefs are honored and duplicate checks are done.168 /// Users call this to assure derefs are honored and duplicate checks are done.
169 fn pre_process(169 fn pre_process(
170 &mut self,170 &mut self,
171 find: impl FnMut(PartialName<'_>) -> Option<Target>,171 find: impl FnMut(PartialNameRef<'_>) -> Option<Target>,
172 make_entry: impl FnMut(usize, RefEdit) -> T,172 make_entry: impl FnMut(usize, RefEdit) -> T,
173 namespace: impl Into<Option<Namespace>>,173 namespace: impl Into<Option<Namespace>>,
174 ) -> Result<(), std::io::Error> {174 ) -> Result<(), std::io::Error> {
@@ -198,7 +198,7 @@ mod ext { · 23 unmodified lines
198 198
199 fn extend_with_splits_of_symbolic_refs(199 fn extend_with_splits_of_symbolic_refs(
200 &mut self,200 &mut self,
201 mut find: impl FnMut(PartialName<'_>) -> Option<Target>,201 mut find: impl FnMut(PartialNameRef<'_>) -> Option<Target>,
202 mut make_entry: impl FnMut(usize, RefEdit) -> E,202 mut make_entry: impl FnMut(usize, RefEdit) -> E,
203 ) -> Result<(), std::io::Error> {203 ) -> Result<(), std::io::Error> {
204 let mut new_edits = Vec::new();204 let mut new_edits = Vec::new();
git-ref/tests/file/log.rs+5−5
@@ -6,7 +6,7 @@ mod line { · 5 unmodified lines
6 #[test]6 #[test]
7 fn newlines_in_message_of_the_input_fails_and_we_trust_signature_writing_validation() -> crate::Result {7 fn newlines_in_message_of_the_input_fails_and_we_trust_signature_writing_validation() -> crate::Result {
8 let line = "0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 commit (initial): c1";8 let line = "0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 commit (initial): c1";
9 let mut line = log::Line::from_bytes(line.as_bytes())?.to_mutable();9 let mut line = log::LineRef::from_bytes(line.as_bytes())?.to_owned();
10 line.message.push_str("and here come\nthe newline");10 line.message.push_str("and here come\nthe newline");
11 let err = line11 let err = line
12 .write_to(&mut Vec::new())12 .write_to(&mut Vec::new())
@@ -20,10 +20,10 @@ mod line { · 7 unmodified lines
20 let lines = &["0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 commit (initial): c1\n", 20 let lines = &["0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 commit (initial): c1\n",
21 "0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 \n"];21 "0000000000000000000000000000000000000000 134385f6d781b7e97062102c6a483440bfda2a03 committer <committer@example.com> 946771200 +0000 \n"];
22 for line in lines {22 for line in lines {
23 let line = log::Line::from_bytes(line.as_bytes())?;23 let line = log::LineRef::from_bytes(line.as_bytes())?;
24 let mut buf = Vec::new();24 let mut buf = Vec::new();
25 line.to_mutable().write_to(&mut buf)?;25 line.to_owned().write_to(&mut buf)?;
26 let same_line = log::Line::from_bytes(&buf)?;26 let same_line = log::LineRef::from_bytes(&buf)?;
27 assert_eq!(line, same_line);27 assert_eq!(line, same_line);
28 }28 }
29 Ok(())29 Ok(())
@@ -75,7 +75,7 @@ mod iter { · 45 unmodified lines
75 }75 }
76 76
77 mod with_buffer_big_enough_for_largest_line {77 mod with_buffer_big_enough_for_largest_line {
78 use git_ref::file::log::mutable::Line;78 use git_ref::file::log::Line;
79 use git_testtools::hex_to_id;79 use git_testtools::hex_to_id;
80 80
81 #[test]81 #[test]
git-ref/tests/file/reference.rs+16−16
@@ -6,7 +6,7 @@ mod reflog { · 5 unmodified lines
6 fn iter() -> crate::Result {6 fn iter() -> crate::Result {
7 let store = file::store_with_packed_refs()?;7 let store = file::store_with_packed_refs()?;
8 let packed = store.packed_buffer()?;8 let packed = store.packed_buffer()?;
9 let r = store.find_existing("main", packed.as_ref())?;9 let r = store.find("main", packed.as_ref())?;
10 let mut buf = Vec::new();10 let mut buf = Vec::new();
11 assert_eq!(r.log_iter(&store, &mut buf)?.expect("log exists").count(), 1);11 assert_eq!(r.log_iter(&store, &mut buf)?.expect("log exists").count(), 1);
12 assert!(r.log_exists(&store), "it exists if its readable");12 assert!(r.log_exists(&store), "it exists if its readable");
@@ -17,7 +17,7 @@ mod reflog { · 4 unmodified lines
17 fn iter_rev() -> crate::Result {17 fn iter_rev() -> crate::Result {
18 let store = file::store_with_packed_refs()?;18 let store = file::store_with_packed_refs()?;
19 let packed = store.packed_buffer()?;19 let packed = store.packed_buffer()?;
20 let r = store.find_existing("main", packed.as_ref())?;20 let r = store.find("main", packed.as_ref())?;
21 let mut buf = [0u8; 256];21 let mut buf = [0u8; 256];
22 assert_eq!(r.log_iter_rev(&store, &mut buf)?.expect("log exists").count(), 1);22 assert_eq!(r.log_iter_rev(&store, &mut buf)?.expect("log exists").count(), 1);
23 Ok(())23 Ok(())
@@ -30,7 +30,7 @@ mod reflog { · 6 unmodified lines
30 #[test]30 #[test]
31 fn iter() -> crate::Result {31 fn iter() -> crate::Result {
32 let store = file::store()?;32 let store = file::store()?;
33 let r = store.loose_find_existing("HEAD")?;33 let r = store.find_loose("HEAD")?;
34 let mut buf = Vec::new();34 let mut buf = Vec::new();
35 assert_eq!(r.log_iter(&store, &mut buf)?.expect("log exists").count(), 1);35 assert_eq!(r.log_iter(&store, &mut buf)?.expect("log exists").count(), 1);
36 assert!(r.log_exists(&store), "it exists if its readable");36 assert!(r.log_exists(&store), "it exists if its readable");
@@ -40,7 +40,7 @@ mod reflog { · 3 unmodified lines
40 #[test]40 #[test]
41 fn iter_rev() -> crate::Result {41 fn iter_rev() -> crate::Result {
42 let store = file::store()?;42 let store = file::store()?;
43 let r = store.loose_find_existing("HEAD")?;43 let r = store.find_loose("HEAD")?;
44 let mut buf = [0u8; 256];44 let mut buf = [0u8; 256];
45 assert_eq!(r.log_iter_rev(&store, &mut buf)?.expect("log exists").count(), 1);45 assert_eq!(r.log_iter_rev(&store, &mut buf)?.expect("log exists").count(), 1);
46 Ok(())46 Ok(())
@@ -60,7 +60,7 @@ mod peel { · 13 unmodified lines
60 #[test]60 #[test]
61 fn one_level() -> crate::Result {61 fn one_level() -> crate::Result {
62 let store = file::store()?;62 let store = file::store()?;
63 let r = store.loose_find_existing("HEAD")?;63 let r = store.find_loose("HEAD")?;
64 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");64 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");
65 65
66 let nr = git_ref::file::loose::Reference::try_from(66 let nr = git_ref::file::loose::Reference::try_from(
@@ -68,13 +68,13 @@ mod peel { · 1 unmodified line
68 )68 )
69 .expect("loose ref");69 .expect("loose ref");
70 assert!(70 assert!(
71 matches!(nr.target.borrow(), git_ref::Target::Peeled(_)),71 matches!(nr.target.to_ref(), git_ref::TargetRef::Peeled(_)),
72 "iteration peels a single level"72 "iteration peels a single level"
73 );73 );
74 assert!(nr.follow_symbolic(&store, None).is_none(), "end of iteration");74 assert!(nr.follow_symbolic(&store, None).is_none(), "end of iteration");
75 assert_eq!(75 assert_eq!(
76 nr.target.borrow(),76 nr.target.to_ref(),
77 git_ref::Target::Peeled(&hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03")),77 git_ref::TargetRef::Peeled(&hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03")),
78 "we still have the peeled target"78 "we still have the peeled target"
79 );79 );
80 Ok(())80 Ok(())
@@ -83,13 +83,13 @@ mod peel { · 2 unmodified lines
83 #[test]83 #[test]
84 fn peel_with_packed_involvement() -> crate::Result {84 fn peel_with_packed_involvement() -> crate::Result {
85 let store = store_with_packed_refs()?;85 let store = store_with_packed_refs()?;
86 let mut head = store.loose_find_existing("HEAD")?;86 let mut head = store.find_loose("HEAD")?;
87 let packed = store.packed_buffer()?;87 let packed = store.packed_buffer()?;
88 let expected = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");88 let expected = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");
89 assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected);89 assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected);
90 assert_eq!(head.target.as_id().map(ToOwned::to_owned), Some(expected));90 assert_eq!(head.target.as_id().map(ToOwned::to_owned), Some(expected));
91 91
92 let mut head = store.find_existing("dt1", packed.as_ref())?;92 let mut head = store.find("dt1", packed.as_ref())?;
93 assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected);93 assert_eq!(head.peel_to_id_in_place(&store, packed.as_ref(), peel::none)?, expected);
94 assert_eq!(head.target().as_id().map(ToOwned::to_owned), Some(expected));94 assert_eq!(head.target().as_id().map(ToOwned::to_owned), Some(expected));
95 Ok(())95 Ok(())
@@ -100,7 +100,7 @@ mod peel { · 4 unmodified lines
100 let store = store_with_packed_refs()?;100 let store = store_with_packed_refs()?;
101 let packed = store.packed_buffer()?;101 let packed = store.packed_buffer()?;
102 102
103 let head = store.find_existing("dt1", packed.as_ref())?;103 let head = store.find("dt1", packed.as_ref())?;
104 assert!(head.is_packed());104 assert!(head.is_packed());
105 assert_eq!(105 assert_eq!(
106 head.target().as_id().map(ToOwned::to_owned),106 head.target().as_id().map(ToOwned::to_owned),
@@ -128,14 +128,14 @@ mod peel { · 21 unmodified lines
128 #[test]128 #[test]
129 fn to_id_multi_hop() -> crate::Result {129 fn to_id_multi_hop() -> crate::Result {
130 let store = file::store()?;130 let store = file::store()?;
131 let mut r = store.loose_find_existing("multi-link")?;131 let mut r = store.find_loose("multi-link")?;
132 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");132 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");
133 133
134 let commit = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");134 let commit = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");
135 assert_eq!(r.peel_to_id_in_place(&store, None, peel::none)?, commit);135 assert_eq!(r.peel_to_id_in_place(&store, None, peel::none)?, commit);
136 assert_eq!(r.name.as_bstr(), "refs/remotes/origin/multi-link-target3");136 assert_eq!(r.name.as_bstr(), "refs/remotes/origin/multi-link-target3");
137 137
138 let mut r = store.loose_find_existing("dt1")?;138 let mut r = store.find_loose("dt1")?;
139 assert_eq!(139 assert_eq!(
140 r.peel_to_id_in_place(&store, None, peel::none)?,140 r.peel_to_id_in_place(&store, None, peel::none)?,
141 hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3"),141 hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3"),
@@ -158,7 +158,7 @@ mod peel { · 16 unmodified lines
158 #[test]158 #[test]
159 fn to_id_cycle() -> crate::Result {159 fn to_id_cycle() -> crate::Result {
160 let store = file::store()?;160 let store = file::store()?;
161 let mut r = store.loose_find_existing("loop-a")?;161 let mut r = store.find_loose("loop-a")?;
162 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");162 assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel");
163 assert_eq!(r.name.as_bstr(), "refs/loop-a");163 assert_eq!(r.name.as_bstr(), "refs/loop-a");
164 164
@@ -203,8 +203,8 @@ mod parse { · 38 unmodified lines
203 let reference =203 let reference =
204 Reference::try_from_path("HEAD".try_into().expect("valid static name"), $input).unwrap();204 Reference::try_from_path("HEAD".try_into().expect("valid static name"), $input).unwrap();
205 assert_eq!(reference.kind(), $kind);205 assert_eq!(reference.kind(), $kind);
206 assert_eq!(reference.target.borrow().as_id(), $id);206 assert_eq!(reference.target.to_ref().as_id(), $id);
207 assert_eq!(reference.target.borrow().as_name(), $ref);207 assert_eq!(reference.target.to_ref().as_name(), $ref);
208 }208 }
209 };209 };
210 }210 }
git-ref/tests/file/store/find.rs+6−6
@@ -8,8 +8,8 @@ mod existing { · 7 unmodified lines
8 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;8 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;
9 let c1 = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");9 let c1 = hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03");
10 let packed = store.packed_buffer()?;10 let packed = store.packed_buffer()?;
11 let r = store.find_existing("main", packed.as_ref())?;11 let r = store.find("main", packed.as_ref())?;
12 assert_eq!(r.target().borrow().as_id().expect("peeled"), c1);12 assert_eq!(r.target().to_ref().as_id().expect("peeled"), c1);
13 assert_eq!(r.name().as_bstr(), "refs/heads/main");13 assert_eq!(r.name().as_bstr(), "refs/heads/main");
14 Ok(())14 Ok(())
15 }15 }
@@ -27,7 +27,7 @@ mod loose { · 11 unmodified lines
27 fn success_and_failure() -> crate::Result {27 fn success_and_failure() -> crate::Result {
28 let store = store()?;28 let store = store()?;
29 for (partial_name, expected_path) in &[("main", Some("refs/heads/main")), ("does-not-exist", None)] {29 for (partial_name, expected_path) in &[("main", Some("refs/heads/main")), ("does-not-exist", None)] {
30 let reference = store.loose_find_existing(*partial_name);30 let reference = store.find_loose(*partial_name);
31 match expected_path {31 match expected_path {
32 Some(expected_path) => assert_eq!(reference?.name.as_bstr(), expected_path),32 Some(expected_path) => assert_eq!(reference?.name.as_bstr(), expected_path),
33 None => match reference {33 None => match reference {
@@ -60,9 +60,9 @@ mod loose { · 26 unmodified lines
60 ("heads/main", "refs/heads/main", git_ref::Kind::Peeled),60 ("heads/main", "refs/heads/main", git_ref::Kind::Peeled),
61 ("refs/heads/main", "refs/heads/main", git_ref::Kind::Peeled),61 ("refs/heads/main", "refs/heads/main", git_ref::Kind::Peeled),
62 ] {62 ] {
63 let reference = store.loose_find(*partial_name)?.expect("exists");63 let reference = store.try_find_loose(*partial_name)?.expect("exists");
64 assert_eq!(reference.name.as_bstr(), expected_path);64 assert_eq!(reference.name.as_bstr(), expected_path);
65 assert_eq!(reference.target.borrow().kind(), *expected_ref_kind);65 assert_eq!(reference.target.to_ref().kind(), *expected_ref_kind);
66 }66 }
67 Ok(())67 Ok(())
68 }68 }
@@ -75,7 +75,7 @@ mod loose { · 6 unmodified lines
75 ("broken", "does not parse", true),75 ("broken", "does not parse", true),
76 ("../escaping", "an invalid ref name", true),76 ("../escaping", "an invalid ref name", true),
77 ] {77 ] {
78 let reference = store.loose_find(*partial_name);78 let reference = store.try_find_loose(*partial_name);
79 if *is_err {79 if *is_err {
80 assert!(reference.is_err(), "{}", reason);80 assert!(reference.is_err(), "{}", reason);
81 } else {81 } else {
git-ref/tests/file/store/iter.rs+2−2
@@ -202,7 +202,7 @@ fn loose_iter_with_prefix() -> crate::Result { · 201 unmodified lines
202 202
203#[test]203#[test]
204fn overlay_iter() -> crate::Result {204fn overlay_iter() -> crate::Result {
205 use git_ref::mutable::Target::*;205 use git_ref::Target::*;
206 206
207 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;207 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;
208 let ref_names = store208 let ref_names = store
@@ -249,7 +249,7 @@ fn overlay_iter_with_prefix_wont_allow_absolute_paths() -> crate::Result { · 40 unmodified lines
249 249
250#[test]250#[test]
251fn overlay_prefixed_iter() -> crate::Result {251fn overlay_prefixed_iter() -> crate::Result {
252 use git_ref::mutable::Target::*;252 use git_ref::Target::*;
253 253
254 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;254 let store = store_at("make_packed_ref_repository_for_overlay.sh")?;
255 let ref_names = store255 let ref_names = store
git-ref/tests/file/transaction/mod.rs+6−5
@@ -1,15 +1,16 @@
1mod prepare_and_commit {1mod prepare_and_commit {
2 use bstr::BString;2 use bstr::BString;
3
3 use git_actor::{Sign, Time};4 use git_actor::{Sign, Time};
4 use git_hash::ObjectId;5 use git_hash::ObjectId;
5 use git_ref::{file, file::log};6 use git_ref::file;
6 7
7 fn reflog_lines(store: &file::Store, name: &str) -> crate::Result<Vec<log::mutable::Line>> {8 fn reflog_lines(store: &file::Store, name: &str) -> crate::Result<Vec<file::log::Line>> {
8 let mut buf = Vec::new();9 let mut buf = Vec::new();
9 let res = store10 let res = store
10 .reflog_iter(name, &mut buf)?11 .reflog_iter(name, &mut buf)?
11 .expect("existing reflog")12 .expect("existing reflog")
12 .map(|l| l.map(log::mutable::Line::from))13 .map(|l| l.map(file::log::Line::from))
13 .collect::<std::result::Result<Vec<_>, _>>()?;14 .collect::<std::result::Result<Vec<_>, _>>()?;
14 Ok(res)15 Ok(res)
15 }16 }
@@ -32,8 +33,8 @@ mod prepare_and_commit { · 16 unmodified lines
32 }33 }
33 }34 }
34 35
35 fn log_line(previous: ObjectId, new: ObjectId, message: impl Into<BString>) -> log::mutable::Line {36 fn log_line(previous: ObjectId, new: ObjectId, message: impl Into<BString>) -> file::log::Line {
36 log::mutable::Line {37 file::log::Line {
37 previous_oid: previous,38 previous_oid: previous,
38 new_oid: new,39 new_oid: new,
39 signature: committer(),40 signature: committer(),
git-ref/tests/file/transaction/prepare_and_commit/create_or_update.rs+27−28
@@ -11,8 +11,8 @@ use git_ref::{ · 10 unmodified lines
11 transaction::{self, PackedRefs},11 transaction::{self, PackedRefs},
12 WriteReflog,12 WriteReflog,
13 },13 },
14 mutable::Target,
15 transaction::{Change, Create, LogChange, RefEdit, RefLog},14 transaction::{Change, Create, LogChange, RefEdit, RefLog},
15 Target,
16};16};
17use git_testtools::hex_to_id;17use git_testtools::hex_to_id;
18use std::convert::TryInto;18use std::convert::TryInto;
@@ -46,7 +46,7 @@ fn reference_with_equally_named_empty_or_non_empty_directory_already_in_place_ca · 27 unmodified lines
46 if *is_empty {46 if *is_empty {
47 let edits = edits?;47 let edits = edits?;
48 assert!(48 assert!(
49 store.loose_find(edits[0].name.to_partial())?.is_some(),49 store.try_find_loose(edits[0].name.to_partial())?.is_some(),
50 "HEAD was created despite a directory being in the way"50 "HEAD was created despite a directory being in the way"
51 );51 );
52 } else {52 } else {
@@ -96,7 +96,7 @@ fn reference_with_old_value_must_exist_when_creating_it() -> crate::Result { · 43 unmodified lines
96#[test]96#[test]
97fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Result {97fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Result {
98 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;98 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
99 let head = store.loose_find("HEAD")?.expect("head exists already");99 let head = store.try_find_loose("HEAD")?.expect("head exists already");
100 let target = head.target;100 let target = head.target;
101 101
102 let res = store.transaction().prepare(102 let res = store.transaction().prepare(
@@ -126,7 +126,7 @@ fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Resu · 23 unmodified lines
126#[test]126#[test]
127fn reference_with_create_only_must_not_exist_already_when_creating_it_if_the_value_does_not_match() -> crate::Result {127fn reference_with_create_only_must_not_exist_already_when_creating_it_if_the_value_does_not_match() -> crate::Result {
128 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;128 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
129 let head = store.loose_find("HEAD")?.expect("head exists already");129 let head = store.try_find_loose("HEAD")?.expect("head exists already");
130 let target = head.target;130 let target = head.target;
131 131
132 let res = store.transaction().prepare(132 let res = store.transaction().prepare(
@@ -211,7 +211,7 @@ fn namespaced_updates_or_deletions_cause_reference_names_to_be_rewritten_and_obs · 78 unmodified lines
211#[test]211#[test]
212fn reference_with_create_only_must_not_exist_already_when_creating_it_unless_the_value_matches() -> crate::Result {212fn reference_with_create_only_must_not_exist_already_when_creating_it_unless_the_value_matches() -> crate::Result {
213 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;213 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
214 let head = store.loose_find("HEAD")?.expect("head exists already");214 let head = store.try_find_loose("HEAD")?.expect("head exists already");
215 let target = head.target;215 let target = head.target;
216 let previous_reflog_count = reflog_lines(&store, "HEAD")?.len();216 let previous_reflog_count = reflog_lines(&store, "HEAD")?.len();
217 217
@@ -289,7 +289,10 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 71 unmodified lines
289 let (_keep, mut store) = empty_store()?;289 let (_keep, mut store) = empty_store()?;
290 store.write_reflog = *reflog_writemode;290 store.write_reflog = *reflog_writemode;
291 let referent = "refs/heads/alt-main";291 let referent = "refs/heads/alt-main";
292 assert!(store.loose_find(referent)?.is_none(), "the reference does not exist");292 assert!(
293 store.try_find_loose(referent)?.is_none(),
294 "the reference does not exist"
295 );
293 let log_ignored = LogChange {296 let log_ignored = LogChange {
294 mode: RefLog::AndReference,297 mode: RefLog::AndReference,
295 force_create_reflog: false,298 force_create_reflog: false,
@@ -325,12 +328,12 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 29 unmodified lines
325 "no split was performed"328 "no split was performed"
326 );329 );
327 330
328 let head = store.loose_find_existing(edits[0].name.to_partial())?;331 let head = store.find_loose(edits[0].name.to_partial())?;
329 assert_eq!(head.name.as_bstr(), "HEAD");332 assert_eq!(head.name.as_bstr(), "HEAD");
330 assert_eq!(head.kind(), git_ref::Kind::Symbolic);333 assert_eq!(head.kind(), git_ref::Kind::Symbolic);
331 assert_eq!(head.target.borrow().as_name(), Some(referent.as_bytes().as_bstr()));334 assert_eq!(head.target.to_ref().as_name(), Some(referent.as_bytes().as_bstr()));
332 assert!(!head.log_exists(&store), "no reflog is written for symbolic ref");335 assert!(!head.log_exists(&store), "no reflog is written for symbolic ref");
333 assert!(store.loose_find(referent)?.is_none(), "referent wasn't created");336 assert!(store.try_find_loose(referent)?.is_none(), "referent wasn't created");
334 337
335 let new_oid = hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242");338 let new_oid = hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242");
336 let new = Target::Peeled(new_oid);339 let new = Target::Peeled(new_oid);
@@ -386,22 +389,22 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 49 unmodified lines
386 ]389 ]
387 );390 );
388 391
389 let head = store.loose_find_existing("HEAD")?;392 let head = store.find_loose("HEAD")?;
390 assert_eq!(393 assert_eq!(
391 head.kind(),394 head.kind(),
392 git_ref::Kind::Symbolic,395 git_ref::Kind::Symbolic,
393 "head is still symbolic, not detached"396 "head is still symbolic, not detached"
394 );397 );
395 assert_eq!(398 assert_eq!(
396 head.target.borrow().as_name(),399 head.target.to_ref().as_name(),
397 Some(referent.as_bytes().as_bstr()),400 Some(referent.as_bytes().as_bstr()),
398 "it still points to the referent"401 "it still points to the referent"
399 );402 );
400 403
401 let referent_ref = store.loose_find_existing(referent)?;404 let referent_ref = store.find_loose(referent)?;
402 assert_eq!(referent_ref.kind(), git_ref::Kind::Peeled, "referent is a peeled ref");405 assert_eq!(referent_ref.kind(), git_ref::Kind::Peeled, "referent is a peeled ref");
403 assert_eq!(406 assert_eq!(
404 referent_ref.target.borrow().as_id(),407 referent_ref.target.to_ref().as_id(),
405 Some(new_oid.as_ref()),408 Some(new_oid.as_ref()),
406 "referent points to desired hash"409 "referent points to desired hash"
407 );410 );
@@ -430,8 +433,8 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 22 unmodified lines
430/// be needed to keep the reflog consistent433/// be needed to keep the reflog consistent
431fn write_reference_to_which_head_points_to_does_not_update_heads_reflog_even_though_it_should() -> crate::Result {434fn write_reference_to_which_head_points_to_does_not_update_heads_reflog_even_though_it_should() -> crate::Result {
432 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;435 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
433 let head = store.loose_find_existing("HEAD")?;436 let head = store.find_loose("HEAD")?;
434 let referent = head.target.borrow().as_name().expect("symbolic ref").to_owned();437 let referent = head.target.to_ref().as_name().expect("symbolic ref").to_owned();
435 let previous_head_reflog = reflog_lines(&store, "HEAD")?;438 let previous_head_reflog = reflog_lines(&store, "HEAD")?;
436 439
437 let new_id = hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc");440 let new_id = hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc");
@@ -497,7 +500,7 @@ fn write_reference_to_which_head_points_to_does_not_update_heads_reflog_even_tho · 59 unmodified lines
497fn packed_refs_are_looked_up_when_checking_existing_values() -> crate::Result {500fn packed_refs_are_looked_up_when_checking_existing_values() -> crate::Result {
498 let (_keep, store) = store_writable("make_packed_ref_repository.sh")?;501 let (_keep, store) = store_writable("make_packed_ref_repository.sh")?;
499 assert!(502 assert!(
500 store.loose_find("main")?.is_none(),503 store.try_find_loose("main")?.is_none(),
501 "no loose main available, it's packed"504 "no loose main available, it's packed"
502 );505 );
503 let new_id = hex_to_id("0000000000000000000000000000000000000001");506 let new_id = hex_to_id("0000000000000000000000000000000000000001");
@@ -528,12 +531,12 @@ fn packed_refs_are_looked_up_when_checking_existing_values() -> crate::Result { · 24 unmodified lines
528 531
529 let packed = store.packed_buffer().unwrap().expect("packed refs is available");532 let packed = store.packed_buffer().unwrap().expect("packed refs is available");
530 assert_eq!(533 assert_eq!(
531 packed.find_existing("main")?.target(),534 packed.find("main")?.target(),
532 old_id,535 old_id,
533 "packed refs aren't rewritten, the change goes into the loose ref instead which shadows packed refs of same name"536 "packed refs aren't rewritten, the change goes into the loose ref instead which shadows packed refs of same name"
534 );537 );
535 assert_eq!(538 assert_eq!(
536 store.loose_find_existing("main")?.target.as_id(),539 store.find_loose("main")?.target.as_id(),
537 Some(new_id.as_ref()),540 Some(new_id.as_ref()),
538 "the new id was written to the loose ref"541 "the new id was written to the loose ref"
539 );542 );
@@ -608,10 +611,10 @@ fn packed_refs_creation_with_packed_refs_mode_prune_removes_original_loose_refs( · 68 unmodified lines
608#[test]611#[test]
609fn packed_refs_creation_with_packed_refs_mode_leave_keeps_original_loose_refs() -> crate::Result {612fn packed_refs_creation_with_packed_refs_mode_leave_keeps_original_loose_refs() -> crate::Result {
610 let (_keep, store) = store_writable("make_packed_ref_repository_for_overlay.sh")?;613 let (_keep, store) = store_writable("make_packed_ref_repository_for_overlay.sh")?;
611 let branch = store.find_existing("newer-as-loose", None)?;614 let branch = store.find("newer-as-loose", None)?;
612 let packed = store.packed_buffer()?.expect("packed-refs");615 let packed = store.packed_buffer()?.expect("packed-refs");
613 assert_ne!(616 assert_ne!(
614 packed.find_existing("newer-as-loose")?.target(),617 packed.find("newer-as-loose")?.target(),
615 branch.target().as_id().expect("peeled"),618 branch.target().as_id().expect("peeled"),
616 "the packed ref is outdated"619 "the packed ref is outdated"
617 );620 );
@@ -662,12 +665,8 @@ fn packed_refs_creation_with_packed_refs_mode_leave_keeps_original_loose_refs() · 44 unmodified lines
662 "the amount of packed refs doesn't change"665 "the amount of packed refs doesn't change"
663 );666 );
664 assert_eq!(667 assert_eq!(
665 packed.find_existing("newer-as-loose")?.target(),668 packed.find("newer-as-loose")?.target(),
666 store669 store.find("newer-as-loose", None)?.target().as_id().expect("peeled"),
667 .find_existing("newer-as-loose", None)?
668 .target()
669 .as_id()
670 .expect("peeled"),
671 "the packed ref is now up to date and the loose ref definitely still exists"670 "the packed ref is now up to date and the loose ref definitely still exists"
672 );671 );
673 Ok(())672 Ok(())
git-ref/tests/file/transaction/prepare_and_commit/delete.rs+31−29
@@ -4,8 +4,8 @@ use crate::file::{ · 3 unmodified lines
4};4};
5use git_lock::acquire::Fail;5use git_lock::acquire::Fail;
6use git_ref::{6use git_ref::{
7 mutable::Target,
8 transaction::{Change, RefEdit, RefLog},7 transaction::{Change, RefEdit, RefLog},
8 Target,
9};9};
10use git_testtools::hex_to_id;10use git_testtools::hex_to_id;
11use std::convert::TryInto;11use std::convert::TryInto;
@@ -58,9 +58,9 @@ fn delete_a_ref_which_is_gone_but_must_exist_fails() -> crate::Result { · 46 unmodified lines
58#[test]58#[test]
59fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result {59fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result {
60 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;60 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
61 let head = store.loose_find_existing("HEAD")?;61 let head = store.find_loose("HEAD")?;
62 assert!(head.log_exists(&store));62 assert!(head.log_exists(&store));
63 let _main = store.loose_find_existing("main")?;63 let _main = store.find_loose("main")?;
64 64
65 let edits = store65 let edits = store
66 .transaction()66 .transaction()
@@ -93,15 +93,15 @@ fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result { · 26 unmodified lines
93 store.reflog_iter_rev("HEAD", &mut [0u8; 128])?.is_none(),93 store.reflog_iter_rev("HEAD", &mut [0u8; 128])?.is_none(),
94 "reflog was deleted"94 "reflog was deleted"
95 );95 );
96 assert!(store.loose_find("HEAD")?.is_none(), "ref was deleted");96 assert!(store.try_find_loose("HEAD")?.is_none(), "ref was deleted");
97 assert!(store.loose_find("main")?.is_some(), "referent still exists");97 assert!(store.try_find_loose("main")?.is_some(), "referent still exists");
98 Ok(())98 Ok(())
99}99}
100 100
101#[test]101#[test]
102fn delete_ref_with_incorrect_previous_value_fails() -> crate::Result {102fn delete_ref_with_incorrect_previous_value_fails() -> crate::Result {
103 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;103 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
104 let head = store.loose_find_existing("HEAD")?;104 let head = store.find_loose("HEAD")?;
105 assert!(head.log_exists(&store));105 assert!(head.log_exists(&store));
106 106
107 let res = store.transaction().prepare(107 let res = store.transaction().prepare(
@@ -123,9 +123,9 @@ fn delete_ref_with_incorrect_previous_value_fails() -> crate::Result { · 15 unmodified lines
123 Ok(_) => unreachable!("must be err"),123 Ok(_) => unreachable!("must be err"),
124 }124 }
125 // everything stays as is125 // everything stays as is
126 let head = store.loose_find_existing("HEAD")?;126 let head = store.find_loose("HEAD")?;
127 assert!(head.log_exists(&store));127 assert!(head.log_exists(&store));
128 let main = store.loose_find_existing("main").expect("referent still exists");128 let main = store.find_loose("main").expect("referent still exists");
129 assert!(main.log_exists(&store));129 assert!(main.log_exists(&store));
130 Ok(())130 Ok(())
131}131}
@@ -133,7 +133,7 @@ fn delete_ref_with_incorrect_previous_value_fails() -> crate::Result { · 1 unmodified line
133#[test]133#[test]
134fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result {134fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result {
135 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;135 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
136 let head = store.loose_find_existing("HEAD")?;136 let head = store.find_loose("HEAD")?;
137 assert!(head.log_exists(&store));137 assert!(head.log_exists(&store));
138 138
139 let edits = store139 let edits = store
@@ -152,9 +152,9 @@ fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result { · 12 unmodified lines
152 .commit(&committer())?;152 .commit(&committer())?;
153 153
154 assert_eq!(edits.len(), 1);154 assert_eq!(edits.len(), 1);
155 let head = store.loose_find_existing("HEAD")?;155 let head = store.find_loose("HEAD")?;
156 assert!(!head.log_exists(&store));156 assert!(!head.log_exists(&store));
157 let main = store.loose_find_existing("main").expect("referent still exists");157 let main = store.find_loose("main").expect("referent still exists");
158 assert!(main.log_exists(&store), "log is untouched, too");158 assert!(main.log_exists(&store), "log is untouched, too");
159 assert_eq!(159 assert_eq!(
160 main.target,160 main.target,
@@ -167,7 +167,7 @@ fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result { · 6 unmodified lines
167#[test]167#[test]
168fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result {168fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result {
169 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;169 let (_keep, store) = store_writable("make_repo_for_reflog.sh")?;
170 let head = store.loose_find_existing("HEAD")?;170 let head = store.find_loose("HEAD")?;
171 assert!(head.log_exists(&store));171 assert!(head.log_exists(&store));
172 172
173 let edits = store173 let edits = store
@@ -186,9 +186,9 @@ fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result { · 12 unmodified lines
186 .commit(&committer())?;186 .commit(&committer())?;
187 187
188 assert_eq!(edits.len(), 2);188 assert_eq!(edits.len(), 2);
189 let head = store.loose_find_existing("HEAD")?;189 let head = store.find_loose("HEAD")?;
190 assert!(!head.log_exists(&store));190 assert!(!head.log_exists(&store));
191 let main = store.loose_find_existing("main").expect("referent still exists");191 let main = store.find_loose("main").expect("referent still exists");
192 assert!(!main.log_exists(&store), "log is removed");192 assert!(!main.log_exists(&store), "log is removed");
193 assert_eq!(193 assert_eq!(
194 main.target,194 main.target,
@@ -203,7 +203,7 @@ fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result { · 8 unmodified lines
203fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() -> crate::Result {203fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() -> crate::Result {
204 let (_keep, store) = empty_store()?;204 let (_keep, store) = empty_store()?;
205 std::fs::write(store.base.join("HEAD"), &b"broken")?;205 std::fs::write(store.base.join("HEAD"), &b"broken")?;
206 assert!(store.loose_find("HEAD").is_err(), "the ref is truly broken");206 assert!(store.try_find_loose("HEAD").is_err(), "the ref is truly broken");
207 207
208 let res = store.transaction().prepare(208 let res = store.transaction().prepare(
209 Some(RefEdit {209 Some(RefEdit {
@@ -233,7 +233,7 @@ fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() -> crate::Res · 23 unmodified lines
233fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Result {233fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Result {
234 let (_keep, store) = empty_store()?;234 let (_keep, store) = empty_store()?;
235 std::fs::write(store.base.join("HEAD"), &b"broken")?;235 std::fs::write(store.base.join("HEAD"), &b"broken")?;
236 assert!(store.loose_find("HEAD").is_err(), "the ref is truly broken");236 assert!(store.try_find_loose("HEAD").is_err(), "the ref is truly broken");
237 237
238 let edits = store238 let edits = store
239 .transaction()239 .transaction()
@@ -250,7 +250,7 @@ fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Res · 10 unmodified lines
250 )?250 )?
251 .commit(&committer())?;251 .commit(&committer())?;
252 252
253 assert!(store.loose_find("HEAD")?.is_none(), "the ref was deleted");253 assert!(store.try_find_loose("HEAD")?.is_none(), "the ref was deleted");
254 assert_eq!(254 assert_eq!(
255 edits,255 edits,
256 vec![RefEdit {256 vec![RefEdit {
@@ -270,7 +270,7 @@ fn store_write_mode_has_no_effect_and_reflogs_are_always_deleted() -> crate::Res · 13 unmodified lines
270 for reflog_writemode in &[git_ref::file::WriteReflog::Normal, git_ref::file::WriteReflog::Disable] {270 for reflog_writemode in &[git_ref::file::WriteReflog::Normal, git_ref::file::WriteReflog::Disable] {
271 let (_keep, mut store) = store_writable("make_repo_for_reflog.sh")?;271 let (_keep, mut store) = store_writable("make_repo_for_reflog.sh")?;
272 store.write_reflog = *reflog_writemode;272 store.write_reflog = *reflog_writemode;
273 assert!(store.loose_find_existing("HEAD")?.log_exists(&store));273 assert!(store.find_loose("HEAD")?.log_exists(&store));
274 assert!(store.packed_buffer()?.is_none(), "there is no pack");274 assert!(store.packed_buffer()?.is_none(), "there is no pack");
275 275
276 let edits = store276 let edits = store
@@ -288,10 +288,7 @@ fn store_write_mode_has_no_effect_and_reflogs_are_always_deleted() -> crate::Res · 11 unmodified lines
288 )?288 )?
289 .commit(&committer())?;289 .commit(&committer())?;
290 assert_eq!(edits.len(), 1);290 assert_eq!(edits.len(), 1);
291 assert!(291 assert!(!store.find_loose("HEAD")?.log_exists(&store), "log was deleted");
292 !store.loose_find_existing("HEAD")?.log_exists(&store),
293 "log was deleted"
294 );
295 assert!(store.packed_buffer()?.is_none(), "there still is no pack");292 assert!(store.packed_buffer()?.is_none(), "there still is no pack");
296 }293 }
297 Ok(())294 Ok(())
@@ -302,11 +299,11 @@ fn packed_refs_are_consulted_when_determining_previous_value_of_ref_to_be_delete · 4 unmodified lines
302) -> crate::Result {299) -> crate::Result {
303 let (_keep, store) = store_writable("make_packed_ref_repository.sh")?;300 let (_keep, store) = store_writable("make_packed_ref_repository.sh")?;
304 assert!(301 assert!(
305 store.loose_find("main")?.is_none(),302 store.try_find_loose("main")?.is_none(),
306 "no loose main available, it's packed"303 "no loose main available, it's packed"
307 );304 );
308 assert!(305 assert!(
309 store.packed_buffer()?.expect("packed").find("main")?.is_some(),306 store.packed_buffer()?.expect("packed").try_find("main")?.is_some(),
310 "packed main is available"307 "packed main is available"
311 );308 );
312 309
@@ -328,7 +325,7 @@ fn packed_refs_are_consulted_when_determining_previous_value_of_ref_to_be_delete · 15 unmodified lines
328 325
329 assert_eq!(edits.len(), 1, "an edit was performed in the packed refs store");326 assert_eq!(edits.len(), 1, "an edit was performed in the packed refs store");
330 let packed = store.packed_buffer()?.expect("packed ref present");327 let packed = store.packed_buffer()?.expect("packed ref present");
331 assert!(packed.find("main")?.is_none(), "no main present after deletion");328 assert!(packed.try_find("main")?.is_none(), "no main present after deletion");
332 Ok(())329 Ok(())
333}330}
334 331
@@ -336,10 +333,10 @@ fn packed_refs_are_consulted_when_determining_previous_value_of_ref_to_be_delete · 1 unmodified line
336fn a_loose_ref_with_old_value_check_and_outdated_packed_refs_value_deletes_both_refs() -> crate::Result {333fn a_loose_ref_with_old_value_check_and_outdated_packed_refs_value_deletes_both_refs() -> crate::Result {
337 let (_keep, store) = store_writable("make_packed_ref_repository_for_overlay.sh")?;334 let (_keep, store) = store_writable("make_packed_ref_repository_for_overlay.sh")?;
338 let packed = store.packed_buffer()?.expect("packed-refs");335 let packed = store.packed_buffer()?.expect("packed-refs");
339 let branch = store.find_existing("newer-as-loose", Some(&packed))?;336 let branch = store.find("newer-as-loose", Some(&packed))?;
340 let branch_id = branch.target().as_id().map(ToOwned::to_owned).expect("peeled");337 let branch_id = branch.target().as_id().map(ToOwned::to_owned).expect("peeled");
341 assert_ne!(338 assert_ne!(
342 packed.find_existing("newer-as-loose")?.target(),339 packed.find("newer-as-loose")?.target(),
343 branch_id,340 branch_id,
344 "the packed ref is outdated"341 "the packed ref is outdated"
345 );342 );
@@ -365,7 +362,9 @@ fn a_loose_ref_with_old_value_check_and_outdated_packed_refs_value_deletes_both_ · 19 unmodified lines
365 "only one edit even though technically two places were changed"362 "only one edit even though technically two places were changed"
366 );363 );
367 assert!(364 assert!(
368 store.find("newer-as-loose", store.packed_buffer()?.as_ref())?.is_none(),365 store
366 .try_find("newer-as-loose", store.packed_buffer()?.as_ref())?
367 .is_none(),
369 "reference is deleted everywhere"368 "reference is deleted everywhere"
370 );369 );
371 Ok(())370 Ok(())
@@ -407,7 +406,10 @@ fn all_contained_references_deletes_the_packed_ref_file_too() { · 35 unmodified lines
407 assert!(packed.is_none(), "it won't make up packed refs");406 assert!(packed.is_none(), "it won't make up packed refs");
408 for edit in edits {407 for edit in edits {
409 assert!(408 assert!(
410 store.find(edit.name.to_partial(), packed.as_ref()).unwrap().is_none(),409 store
410 .try_find(edit.name.to_partial(), packed.as_ref())
411 .unwrap()
412 .is_none(),
411 "delete ref cannot be found"413 "delete ref cannot be found"
412 );414 );
413 }415 }
git-ref/tests/packed/find.rs+25−21
@@ -1,6 +1,6 @@
1use std::convert::{TryFrom, TryInto};1use std::convert::{TryFrom, TryInto};
2 2
3use git_ref::{packed, PartialName};3use git_ref::{packed, PartialNameRef};
4use git_testtools::fixture_path;4use git_testtools::fixture_path;
5 5
6use crate::{6use crate::{
@@ -11,7 +11,7 @@ use crate::{ · 4 unmodified lines
11#[test]11#[test]
12fn a_lock_file_would_not_be_a_valid_partial_name() {12fn a_lock_file_would_not_be_a_valid_partial_name() {
13 // doesn't really belong here but want to make sure refname validation works as expected.13 // doesn't really belong here but want to make sure refname validation works as expected.
14 let err = PartialName::try_from("heads/hello.lock").expect_err("this should fail");14 let err = PartialNameRef::try_from("heads/hello.lock").expect_err("this should fail");
15 assert_eq!(err.to_string(), "A reference must be a valid tag name as well");15 assert_eq!(err.to_string(), "A reference must be a valid tag name as well");
16}16}
17 17
@@ -22,9 +22,9 @@ fn all_iterable_refs_can_be_found() -> crate::Result { · 4 unmodified lines
22 22
23 for reference in packed_refs.iter()? {23 for reference in packed_refs.iter()? {
24 let reference = reference?;24 let reference = reference?;
25 let found = packed_refs.find(reference.name)?.expect("reference exists");25 let found = packed_refs.try_find(reference.name)?.expect("reference exists");
26 assert_eq!(reference, found, "both refs are exactly the same");26 assert_eq!(reference, found, "both refs are exactly the same");
27 let found = packed_refs.find_existing(reference.name)?;27 let found = packed_refs.find(reference.name)?;
28 assert_eq!(reference, found);28 assert_eq!(reference, found);
29 }29 }
30 Ok(())30 Ok(())
@@ -33,7 +33,7 @@ fn all_iterable_refs_can_be_found() -> crate::Result { · 2 unmodified lines
33#[test]33#[test]
34fn binary_search_a_name_past_the_end_of_the_packed_refs_file() -> crate::Result {34fn binary_search_a_name_past_the_end_of_the_packed_refs_file() -> crate::Result {
35 let packed_refs = packed::Buffer::open(fixture_path("packed-refs").join("triggers-out-of-bounds"), 32)?;35 let packed_refs = packed::Buffer::open(fixture_path("packed-refs").join("triggers-out-of-bounds"), 32)?;
36 assert!(packed_refs.find("v0.0.1")?.is_none());36 assert!(packed_refs.try_find("v0.0.1")?.is_none());
37 Ok(())37 Ok(())
38}38}
39 39
@@ -49,7 +49,7 @@ c4cebba92af964f2d126be90b8a6298c4cf84d45 refs/tags/git-actor-v0.1.0 · 9 unmodified lines
49 let buf = packed::Buffer::open(path, 1024)?;49 let buf = packed::Buffer::open(path, 1024)?;
50 let name = "refs/tags/TEST-0.0.1";50 let name = "refs/tags/TEST-0.0.1";
51 assert_eq!(51 assert_eq!(
52 buf.find(name)?.expect("reference exists"),52 buf.try_find(name)?.expect("reference exists"),
53 packed::Reference {53 packed::Reference {
54 name: name.try_into()?,54 name: name.try_into()?,
55 target: "916840c0e2f67d370291042cb5274a597f4fa9bc".into(),55 target: "916840c0e2f67d370291042cb5274a597f4fa9bc".into(),
@@ -58,7 +58,7 @@ c4cebba92af964f2d126be90b8a6298c4cf84d45 refs/tags/git-actor-v0.1.0 · 2 unmodified lines
58 );58 );
59 let name = "refs/tags/git-actor-v0.1.0";59 let name = "refs/tags/git-actor-v0.1.0";
60 assert_eq!(60 assert_eq!(
61 buf.find(name)?.expect("reference exists"),61 buf.try_find(name)?.expect("reference exists"),
62 packed::Reference {62 packed::Reference {
63 name: name.try_into()?,63 name: name.try_into()?,
64 target: "c4cebba92af964f2d126be90b8a6298c4cf84d45".into(),64 target: "c4cebba92af964f2d126be90b8a6298c4cf84d45".into(),
@@ -67,7 +67,7 @@ c4cebba92af964f2d126be90b8a6298c4cf84d45 refs/tags/git-actor-v0.1.0 · 2 unmodified lines
67 );67 );
68 let name = "refs/tags/git-actor-v0.1.1";68 let name = "refs/tags/git-actor-v0.1.1";
69 assert_eq!(69 assert_eq!(
70 buf.find(name)?.expect("reference exists"),70 buf.try_find(name)?.expect("reference exists"),
71 packed::Reference {71 packed::Reference {
72 name: name.try_into()?,72 name: name.try_into()?,
73 target: "0b92c8a256ae06c189e3b9c30b646d62ac8f7d10".into(),73 target: "0b92c8a256ae06c189e3b9c30b646d62ac8f7d10".into(),
@@ -83,50 +83,50 @@ fn partial_name_to_full_name_conversion_rules_are_applied() -> crate::Result { · 9 unmodified lines
83 let packed = store.packed_buffer()?.expect("packed-refs exists");83 let packed = store.packed_buffer()?.expect("packed-refs exists");
84 84
85 assert_eq!(85 assert_eq!(
86 store.loose_find_existing("origin")?.name.as_bstr(),86 store.find_loose("origin")?.name.as_bstr(),
87 "refs/remotes/origin/HEAD",87 "refs/remotes/origin/HEAD",
88 "a special that only applies to loose refs"88 "a special that only applies to loose refs"
89 );89 );
90 assert!(90 assert!(
91 packed.find("origin")?.is_none(),91 packed.try_find("origin")?.is_none(),
92 "packed refs don't have this special case as they don't store HEADs or symrefs"92 "packed refs don't have this special case as they don't store HEADs or symrefs"
93 );93 );
94 assert_eq!(94 assert_eq!(
95 store.loose_find_existing("HEAD")?.name.as_bstr(),95 store.find_loose("HEAD")?.name.as_bstr(),
96 "HEAD",96 "HEAD",
97 "HEAD can be found in loose stores"97 "HEAD can be found in loose stores"
98 );98 );
99 assert!(99 assert!(
100 packed.find("HEAD")?.is_none(),100 packed.try_find("HEAD")?.is_none(),
101 "packed refs definitely don't contain HEAD"101 "packed refs definitely don't contain HEAD"
102 );102 );
103 assert_eq!(103 assert_eq!(
104 packed.find("head-or-tag")?.expect("present").name.as_bstr(),104 packed.try_find("head-or-tag")?.expect("present").name.as_bstr(),
105 "refs/tags/head-or-tag",105 "refs/tags/head-or-tag",
106 "it finds tags first"106 "it finds tags first"
107 );107 );
108 assert_eq!(108 assert_eq!(
109 packed.find("heads/head-or-tag")?.expect("present").name.as_bstr(),109 packed.try_find("heads/head-or-tag")?.expect("present").name.as_bstr(),
110 "refs/heads/head-or-tag",110 "refs/heads/head-or-tag",
111 "it finds heads when disambiguated"111 "it finds heads when disambiguated"
112 );112 );
113 assert_eq!(113 assert_eq!(
114 packed.find("main")?.expect("present").name.as_bstr(),114 packed.try_find("main")?.expect("present").name.as_bstr(),
115 "refs/heads/main",115 "refs/heads/main",
116 "it finds local heads before remote ones"116 "it finds local heads before remote ones"
117 );117 );
118 assert_eq!(118 assert_eq!(
119 packed.find("origin/main")?.expect("present").name.as_bstr(),119 packed.try_find("origin/main")?.expect("present").name.as_bstr(),
120 "refs/remotes/origin/main",120 "refs/remotes/origin/main",
121 "it finds remote heads when disambiguated"121 "it finds remote heads when disambiguated"
122 );122 );
123 assert_eq!(123 assert_eq!(
124 packed.find("remotes/origin/main")?.expect("present").name.as_bstr(),124 packed.try_find("remotes/origin/main")?.expect("present").name.as_bstr(),
125 "refs/remotes/origin/main",125 "refs/remotes/origin/main",
126 "more specification is possible, too"126 "more specification is possible, too"
127 );127 );
128 assert_eq!(128 assert_eq!(
129 packed.find("tag-object")?.expect("present"),129 packed.try_find("tag-object")?.expect("present"),
130 packed::Reference {130 packed::Reference {
131 name: "refs/tags/tag-object".try_into()?,131 name: "refs/tags/tag-object".try_into()?,
132 target: "b3109a7e51fc593f85b145a76c70ddd1d133fafd".into(),132 target: "b3109a7e51fc593f85b145a76c70ddd1d133fafd".into(),
@@ -150,7 +150,7 @@ bogus refs/tags/git-actor-v0.1.0 · 17 unmodified lines
150 150
151 let name = "refs/tags/git-actor-v0.1.1";151 let name = "refs/tags/git-actor-v0.1.1";
152 assert_eq!(152 assert_eq!(
153 buf.find(name)?.expect("reference exists"),153 buf.try_find(name)?.expect("reference exists"),
154 packed::Reference {154 packed::Reference {
155 name: name.try_into()?,155 name: name.try_into()?,
156 target: "0b92c8a256ae06c189e3b9c30b646d62ac8f7d10".into(),156 target: "0b92c8a256ae06c189e3b9c30b646d62ac8f7d10".into(),
@@ -160,7 +160,7 @@ bogus refs/tags/git-actor-v0.1.0 · 3 unmodified lines
160 160
161 for failing_name in &["refs/tags/TEST-0.0.1", "refs/tags/git-actor-v0.1.0"] {161 for failing_name in &["refs/tags/TEST-0.0.1", "refs/tags/git-actor-v0.1.0"] {
162 assert_eq!(162 assert_eq!(
163 buf.find(*failing_name)163 buf.try_find(*failing_name)
164 .expect_err("it should detect an err")164 .expect_err("it should detect an err")
165 .to_string(),165 .to_string(),
166 "The reference could not be parsed"166 "The reference could not be parsed"
@@ -178,7 +178,11 @@ fn find_speed() -> crate::Result { · 11 unmodified lines
178 for r in packed.iter()?.take(10_000) {178 for r in packed.iter()?.take(10_000) {
179 num_refs += 1;179 num_refs += 1;
180 let r = r?;180 let r = r?;
181 assert_eq!(packed.find(r.name)?.expect("ref was found"), r, "the refs are the same");181 assert_eq!(
182 packed.try_find(r.name)?.expect("ref was found"),
183 r,
184 "the refs are the same"
185 );
182 }186 }
183 let elapsed = start.elapsed().as_secs_f32();187 let elapsed = start.elapsed().as_secs_f32();
184 eprintln!(188 eprintln!(
git-ref/tests/packed/open.rs+1−1
@@ -27,7 +27,7 @@ fn unsorted_buffers_or_those_without_a_header_can_be_opened_and_searched() { · 26 unmodified lines
27 .unwrap();27 .unwrap();
28 for packed_ref in buffer.iter().unwrap().map(Result::unwrap) {28 for packed_ref in buffer.iter().unwrap().map(Result::unwrap) {
29 let found_ref = buffer29 let found_ref = buffer
30 .find_existing(packed_ref.name)30 .find(packed_ref.name)
31 .expect("ref can be found as buffer is sorted");31 .expect("ref can be found as buffer is sorted");
32 assert_eq!(32 assert_eq!(
33 found_ref, packed_ref,33 found_ref, packed_ref,
git-ref/tests/transaction/mod.rs+5−7
@@ -3,9 +3,8 @@ mod refedit_ext { · 2 unmodified lines
3 3
4 use bstr::{BString, ByteSlice};4 use bstr::{BString, ByteSlice};
5 use git_ref::{5 use git_ref::{
6 mutable::Target,
7 transaction::{Change, Create, RefEdit, RefEditsExt, RefLog},6 transaction::{Change, Create, RefEdit, RefEditsExt, RefLog},
8 PartialName,7 PartialNameRef, Target,
9 };8 };
10 9
11 #[derive(Default)]10 #[derive(Default)]
@@ -26,7 +25,7 @@ mod refedit_ext { · 14 unmodified lines
26 },25 },
27 }26 }
28 }27 }
29 fn find_existing(&self, name: PartialName<'_>) -> Option<Target> {28 fn find_existing(&self, name: PartialNameRef<'_>) -> Option<Target> {
30 self.targets.borrow_mut().remove(name.as_bstr())29 self.targets.borrow_mut().remove(name.as_bstr())
31 }30 }
32 }31 }
@@ -149,16 +148,15 @@ mod refedit_ext { · 116 unmodified lines
149 148
150 use git_hash::ObjectId;149 use git_hash::ObjectId;
151 use git_ref::{150 use git_ref::{
152 mutable::Target,
153 transaction::{Change, Create, LogChange, RefEdit, RefEditsExt, RefLog},151 transaction::{Change, Create, LogChange, RefEdit, RefEditsExt, RefLog},
154 FullName, PartialName,152 FullNameRef, PartialNameRef, Target,
155 };153 };
156 use git_testtools::hex_to_id;154 use git_testtools::hex_to_id;
157 155
158 use crate::transaction::refedit_ext::MockStore;156 use crate::transaction::refedit_ext::MockStore;
159 157
160 fn find<'a>(edits: &'a [RefEdit], name: &str) -> &'a RefEdit {158 fn find<'a>(edits: &'a [RefEdit], name: &str) -> &'a RefEdit {
161 let name: FullName = name.try_into().unwrap();159 let name: FullNameRef = name.try_into().unwrap();
162 edits160 edits
163 .iter()161 .iter()
164 .find(|e| e.name.as_bstr() == name.as_bstr())162 .find(|e| e.name.as_bstr() == name.as_bstr())
@@ -229,7 +227,7 @@ mod refedit_ext { · 64 unmodified lines
229 next_item: Cell<bool>,227 next_item: Cell<bool>,
230 }228 }
231 impl Cycler {229 impl Cycler {
232 fn find_existing(&self, _name: PartialName<'_>) -> Option<Target> {230 fn find_existing(&self, _name: PartialNameRef<'_>) -> Option<Target> {
233 let item: bool = self.next_item.get();231 let item: bool = self.next_item.get();
234 self.next_item.set(!item);232 self.next_item.set(!item);
235 Some(Target::Symbolic(233 Some(Target::Symbolic(
git-repository/Cargo.toml+1−1
@@ -42,7 +42,7 @@ git-validate = { version = "^0.5.0", path = "../git-validate" } · 41 unmodified lines
42git-odb = { version ="0.20.0", path = "../git-odb" }42git-odb = { version ="0.20.0", path = "../git-odb" }
43git-hash = { version = "^0.5.0", path = "../git-hash" }43git-hash = { version = "^0.5.0", path = "../git-hash" }
44git-object = { version ="0.12.0", path = "../git-object" }44git-object = { version ="0.12.0", path = "../git-object" }
45git-actor = { version ="^0.4.0", path = "../git-actor" }45git-actor = { version ="^0.5.0", path = "../git-actor" }
46git-pack = { version ="^0.9.0", path = "../git-pack" }46git-pack = { version ="^0.9.0", path = "../git-pack" }
47 47
48git-url = { version = "0.3.0", path = "../git-url", optional = true }48git-url = { version = "0.3.0", path = "../git-url", optional = true }
git-repository/src/easy/ext/reference.rs+4−5
@@ -10,9 +10,8 @@ use git_actor as actor; · 9 unmodified lines
10use git_lock as lock;10use git_lock as lock;
11use git_ref::{11use git_ref::{
12 file::find::Error,12 file::find::Error,
13 mutable::Target,
14 transaction::{Change, Create, RefEdit},13 transaction::{Change, Create, RefEdit},
15 PartialName,14 PartialNameRef, Target,
16};15};
17 16
18/// Obtain and alter references comfortably17/// Obtain and alter references comfortably
@@ -77,7 +76,7 @@ pub trait ReferenceAccessExt: easy::Access + Sized { · 58 unmodified lines
77 76
78 fn find_reference<'a, Name, E>(&self, name: Name) -> Result<Reference<'_, Self>, reference::find::existing::Error>77 fn find_reference<'a, Name, E>(&self, name: Name) -> Result<Reference<'_, Self>, reference::find::existing::Error>
79 where78 where
80 Name: TryInto<PartialName<'a>, Error = E>,79 Name: TryInto<PartialNameRef<'a>, Error = E>,
81 Error: From<E>,80 Error: From<E>,
82 {81 {
83 self.try_find_reference(name)?82 self.try_find_reference(name)?
@@ -86,14 +85,14 @@ pub trait ReferenceAccessExt: easy::Access + Sized { · 2 unmodified lines
86 85
87 fn try_find_reference<'a, Name, E>(&self, name: Name) -> Result<Option<Reference<'_, Self>>, reference::find::Error>86 fn try_find_reference<'a, Name, E>(&self, name: Name) -> Result<Option<Reference<'_, Self>>, reference::find::Error>
88 where87 where
89 Name: TryInto<PartialName<'a>, Error = E>,88 Name: TryInto<PartialNameRef<'a>, Error = E>,
90 Error: From<E>,89 Error: From<E>,
91 {90 {
92 let state = self.state();91 let state = self.state();
93 let repo = self.repo()?;92 let repo = self.repo()?;
94 match repo93 match repo
95 .refs94 .refs
96 .find(name, state.assure_packed_refs_uptodate(&repo.refs)?.as_ref())95 .try_find(name, state.assure_packed_refs_uptodate(&repo.refs)?.as_ref())
97 {96 {
98 Ok(r) => match r {97 Ok(r) => match r {
99 Some(r) => Ok(Some(Reference::from_file_ref(r, self))),98 Some(r) => Ok(Some(Reference::from_file_ref(r, self))),
git-repository/src/easy/reference.rs+5−5
@@ -12,7 +12,7 @@ use git_ref as refs; · 11 unmodified lines
12pub(crate) enum Backing {12pub(crate) enum Backing {
13 OwnedPacked {13 OwnedPacked {
14 /// The validated full name of the reference.14 /// The validated full name of the reference.
15 name: refs::mutable::FullName,15 name: refs::FullName,
16 /// The target object id of the reference, hex encoded.16 /// The target object id of the reference, hex encoded.
17 target: ObjectId,17 target: ObjectId,
18 /// The fully peeled object id, hex encoded, that the ref is ultimately pointing to18 /// The fully peeled object id, hex encoded, that the ref is ultimately pointing to
@@ -107,19 +107,19 @@ where · 88 unmodified lines
107 access,107 access,
108 }108 }
109 }109 }
110 pub fn target(&self) -> refs::mutable::Target {110 pub fn target(&self) -> refs::Target {
111 match self.backing.as_ref().expect("always set") {111 match self.backing.as_ref().expect("always set") {
112 Backing::OwnedPacked { target, .. } => refs::mutable::Target::Peeled(target.to_owned()),112 Backing::OwnedPacked { target, .. } => refs::Target::Peeled(target.to_owned()),
113 Backing::LooseFile(r) => r.target.clone(),113 Backing::LooseFile(r) => r.target.clone(),
114 }114 }
115 }115 }
116 116
117 pub fn name(&self) -> refs::FullName<'_> {117 pub fn name(&self) -> refs::FullNameRef<'_> {
118 match self.backing.as_ref().expect("always set") {118 match self.backing.as_ref().expect("always set") {
119 Backing::OwnedPacked { name, .. } => name,119 Backing::OwnedPacked { name, .. } => name,
120 Backing::LooseFile(r) => &r.name,120 Backing::LooseFile(r) => &r.name,
121 }121 }
122 .borrow()122 .to_ref()
123 }123 }
124 124
125 pub fn peel_to_oid_in_place(&mut self) -> Result<Oid<'repo, A>, peel_to_oid_in_place::Error> {125 pub fn peel_to_oid_in_place(&mut self) -> Result<Oid<'repo, A>, peel_to_oid_in_place::Error> {
git-repository/src/path/is_git.rs+1−1
@@ -42,7 +42,7 @@ pub fn is_git(git_dir: impl AsRef<Path>) -> Result<crate::Kind, Error> { · 41 unmodified lines
42 42
43 {43 {
44 let refs = git_ref::file::Store::at(&dot_git, Default::default());44 let refs = git_ref::file::Store::at(&dot_git, Default::default());
45 let head = refs.loose_find_existing("HEAD")?;45 let head = refs.find_loose("HEAD")?;
46 if head.name.as_bstr() != "HEAD" {46 if head.name.as_bstr() != "HEAD" {
47 return Err(Error::MisplacedHead(head.name.into_inner()));47 return Err(Error::MisplacedHead(head.name.into_inner()));
48 }48 }
git-repository/tests/reference/mod.rs+1−1
@@ -19,7 +19,7 @@ mod find { · 18 unmodified lines
19 19
20 assert_eq!(20 assert_eq!(
21 packed_tag_ref.target(),21 packed_tag_ref.target(),
22 refs::mutable::Target::Peeled(hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3")),22 refs::Target::Peeled(hex_to_id("4c3f4cce493d7beb45012e478021b5f65295e5a3")),
23 "it points to a tag object"23 "it points to a tag object"
24 );24 );
25 25
gitoxide-core/src/hours.rs+1−1
@@ -49,7 +49,7 @@ where · 48 unmodified lines
49 let packed = repo.refs.packed_buffer()?;49 let packed = repo.refs.packed_buffer()?;
50 let commit_id = repo50 let commit_id = repo
51 .refs51 .refs
52 .find_existing(refname.to_string_lossy().as_ref(), packed.as_ref())?52 .find(refname.to_string_lossy().as_ref(), packed.as_ref())?
53 .peel_to_id_in_place(&repo.refs, packed.as_ref(), |oid, buf| {53 .peel_to_id_in_place(&repo.refs, packed.as_ref(), |oid, buf| {
54 repo.odb54 repo.odb
55 .find(oid, buf, &mut pack::cache::Never)55 .find(oid, buf, &mut pack::cache::Never)
gitoxide-core/src/pack/create.rs+1−1
@@ -117,7 +117,7 @@ where · 116 unmodified lines
117 let refs = &repo.refs;117 let refs = &repo.refs;
118 let repo = Arc::clone(&repo);118 let repo = Arc::clone(&repo);
119 move |_| {119 move |_| {
120 refs.find_existing(tip.as_ref().to_string_lossy().as_ref(), packed.as_ref())120 refs.find(tip.as_ref().to_string_lossy().as_ref(), packed.as_ref())
121 .map_err(anyhow::Error::from)121 .map_err(anyhow::Error::from)
122 .and_then(|mut r| {122 .and_then(|mut r| {
123 r.peel_to_id_in_place(refs, packed.as_ref(), |oid, buf| {123 r.peel_to_id_in_place(refs, packed.as_ref(), |oid, buf| {