Unified · Split
| @@ -9,7 +9,10 @@ mod method { · 8 unmodified lines | |||
| 9 | fn target() -> crate::Result { | 9 | fn target() -> crate::Result { |
| 10 | let fixture = fixture_bytes("tag", "signed.txt"); | 10 | let fixture = fixture_bytes("tag", "signed.txt"); |
| 11 | let tag = Tag::from_bytes(&fixture)?; | 11 | let tag = Tag::from_bytes(&fixture)?; |
| 12 | assert_eq!(tag.target(), hex_to_id("ffa700b4aca13b80cb6b98a078e7c96804f8e0ec")); | 12 | assert_eq!( |
| 13 | tag.target.borrow(), | ||
| 14 | hex_to_id("ffa700b4aca13b80cb6b98a078e7c96804f8e0ec") | ||
| 15 | ); | ||
| 13 | assert_eq!(tag.target, "ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bytes()); | 16 | assert_eq!(tag.target, "ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bytes()); |
| 14 | Ok(()) | 17 | Ok(()) |
| 15 | } | 18 | } |
| @@ -33,6 +33,7 @@ impl TryFrom<BString> for FullName { · 32 unmodified lines | |||
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | // TODO: remove this one to be consistent with borrowed version | ||
| 36 | impl AsRef<BStr> for FullName { | 37 | impl AsRef<BStr> for FullName { |
| 37 | fn as_ref(&self) -> &BStr { | 38 | fn as_ref(&self) -> &BStr { |
| 38 | self.0.as_bstr() | 39 | self.0.as_bstr() |
| @@ -59,6 +60,10 @@ impl FullName { · 20 unmodified lines | |||
| 59 | pub fn into_inner(self) -> BString { | 60 | pub fn into_inner(self) -> BString { |
| 60 | self.0 | 61 | self.0 |
| 61 | } | 62 | } |
| 63 | /// Return ourselves as byte string which is a valid refname | ||
| 64 | pub fn as_bstr(&self) -> &BStr { | ||
| 65 | self.0.as_bstr() | ||
| 66 | } | ||
| 62 | } | 67 | } |
| 63 | 68 | ||
| 64 | /// Denotes a ref target, equivalent to [`Kind`][super::Kind], but with mutable data. | 69 | /// Denotes a ref target, equivalent to [`Kind`][super::Kind], but with mutable data. |
| @@ -119,11 +119,12 @@ impl file::Store { · 118 unmodified lines | |||
| 119 | } | 119 | } |
| 120 | Some(c) => c, | 120 | Some(c) => c, |
| 121 | }; | 121 | }; |
| 122 | Ok(Some( | 122 | Ok(Some({ |
| 123 | file::Reference::try_from_path(self, &relative_path, &contents) | 123 | let full_name = path_to_name(&relative_path); |
| 124 | file::Reference::try_from_path(self, FullName(full_name), &contents) | ||
| 124 | .map(file::loose_then_packed::Reference::Loose) | 125 | .map(file::loose_then_packed::Reference::Loose) |
| 125 | .map_err(|err| Error::ReferenceCreation { err, relative_path })?, | 126 | .map_err(|err| Error::ReferenceCreation { err, relative_path })? |
| 126 | )) | 127 | })) |
| 127 | } | 128 | } |
| 128 | } | 129 | } |
| 129 | 130 | ||
| @@ -256,4 +257,5 @@ mod error { · 126 unmodified lines | |||
| 256 | } | 257 | } |
| 257 | } | 258 | } |
| 258 | } | 259 | } |
| 260 | use crate::mutable::FullName; | ||
| 259 | pub use error::Error; | 261 | pub use error::Error; |
| @@ -1,5 +1,5 @@ | |||
| 1 | use crate::store::file; | 1 | use crate::{mutable::FullName, store::file}; |
| 2 | use bstr::{BString, ByteSlice}; | 2 | use bstr::ByteSlice; |
| 3 | use git_features::fs::walkdir::DirEntryIter; | 3 | use git_features::fs::walkdir::DirEntryIter; |
| 4 | use os_str_bytes::OsStrBytes; | 4 | use os_str_bytes::OsStrBytes; |
| 5 | use std::{ | 5 | use std::{ |
| @@ -11,31 +11,20 @@ use std::{ · 5 unmodified lines | |||
| 11 | pub(in crate::store::file) struct SortedLoosePaths { | 11 | pub(in crate::store::file) struct SortedLoosePaths { |
| 12 | base: PathBuf, | 12 | base: PathBuf, |
| 13 | file_walk: DirEntryIter, | 13 | file_walk: DirEntryIter, |
| 14 | mode: LoosePathsMode, | ||
| 15 | } | ||
| 16 | |||
| 17 | enum LoosePathsMode { | ||
| 18 | Paths, | ||
| 19 | PathsAndNames, | ||
| 20 | } | 14 | } |
| 21 | 15 | ||
| 22 | impl SortedLoosePaths { | 16 | impl SortedLoosePaths { |
| 23 | pub fn at_root(path: impl AsRef<Path>, base: impl Into<PathBuf>) -> Self { | ||
| 24 | Self::new(path.as_ref(), base.into(), LoosePathsMode::Paths) | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn at_root_with_names(path: impl AsRef<Path>, base: impl Into<PathBuf>) -> Self { | 17 | pub fn at_root_with_names(path: impl AsRef<Path>, base: impl Into<PathBuf>) -> Self { |
| 28 | Self::new(path.as_ref(), base.into(), LoosePathsMode::PathsAndNames) | ||
| 29 | } | ||
| 30 | |||
| 31 | fn new(path: &Path, base: PathBuf, mode: LoosePathsMode) -> Self { | ||
| 32 | let file_walk = git_features::fs::walkdir_sorted_new(path).into_iter(); | 18 | let file_walk = git_features::fs::walkdir_sorted_new(path).into_iter(); |
| 33 | SortedLoosePaths { base, file_walk, mode } | 19 | SortedLoosePaths { |
| 20 | base: base.into(), | ||
| 21 | file_walk, | ||
| 22 | } | ||
| 34 | } | 23 | } |
| 35 | } | 24 | } |
| 36 | 25 | ||
| 37 | impl Iterator for SortedLoosePaths { | 26 | impl Iterator for SortedLoosePaths { |
| 38 | type Item = std::io::Result<(PathBuf, Option<BString>)>; | 27 | type Item = std::io::Result<(PathBuf, FullName)>; |
| 39 | 28 | ||
| 40 | fn next(&mut self) -> Option<Self::Item> { | 29 | fn next(&mut self) -> Option<Self::Item> { |
| 41 | while let Some(entry) = self.file_walk.next() { | 30 | while let Some(entry) = self.file_walk.next() { |
| @@ -52,15 +41,11 @@ impl Iterator for SortedLoosePaths { · 10 unmodified lines | |||
| 52 | #[cfg(windows)] | 41 | #[cfg(windows)] |
| 53 | let full_name: Vec<u8> = full_name.into_owned().replace(b"\\", b"/"); | 42 | let full_name: Vec<u8> = full_name.into_owned().replace(b"\\", b"/"); |
| 54 | 43 | ||
| 55 | use LoosePathsMode::*; | ||
| 56 | if git_validate::reference::name_partial(full_name.as_bstr()).is_ok() { | 44 | if git_validate::reference::name_partial(full_name.as_bstr()).is_ok() { |
| 57 | let name = match self.mode { | 45 | #[cfg(not(windows))] |
| 58 | Paths => None, | 46 | let name = FullName(full_name.into_owned().into()); |
| 59 | #[cfg(not(windows))] | 47 | #[cfg(windows)] |
| 60 | PathsAndNames => Some(full_name.into_owned().into()), | 48 | let name = FullName(full_name.into()); |
| 61 | #[cfg(windows)] | ||
| 62 | PathsAndNames => Some(full_name.into()), | ||
| 63 | }; | ||
| 64 | return Some(Ok((full_path, name))); | 49 | return Some(Ok((full_path, name))); |
| 65 | } else { | 50 | } else { |
| 66 | continue; | 51 | continue; |
| @@ -86,7 +71,7 @@ impl<'a> Loose<'a> { · 19 unmodified lines | |||
| 86 | pub fn at_root(store: &'a file::Store, root: impl AsRef<Path>, base: impl Into<PathBuf>) -> Self { | 71 | pub fn at_root(store: &'a file::Store, root: impl AsRef<Path>, base: impl Into<PathBuf>) -> Self { |
| 87 | Loose { | 72 | Loose { |
| 88 | parent: store, | 73 | parent: store, |
| 89 | ref_paths: SortedLoosePaths::at_root(root, base), | 74 | ref_paths: SortedLoosePaths::at_root_with_names(root, base), |
| 90 | buf: Vec::new(), | 75 | buf: Vec::new(), |
| 91 | } | 76 | } |
| 92 | } | 77 | } |
| @@ -97,26 +82,25 @@ impl<'a> Iterator for Loose<'a> { · 4 unmodified lines | |||
| 97 | 82 | ||
| 98 | fn next(&mut self) -> Option<Self::Item> { | 83 | fn next(&mut self) -> Option<Self::Item> { |
| 99 | self.ref_paths.next().map(|res| { | 84 | self.ref_paths.next().map(|res| { |
| 100 | res.map_err(loose::Error::Traversal) | 85 | res.map_err(loose::Error::Traversal).and_then(|(validated_path, name)| { |
| 101 | .and_then(|(validated_path, _name)| { | 86 | std::fs::File::open(&validated_path) |
| 102 | std::fs::File::open(&validated_path) | 87 | .and_then(|mut f| { |
| 103 | .and_then(|mut f| { | 88 | self.buf.clear(); |
| 104 | self.buf.clear(); | 89 | f.read_to_end(&mut self.buf) |
| 105 | f.read_to_end(&mut self.buf) | 90 | }) |
| 106 | }) | 91 | .map_err(loose::Error::ReadFileContents) |
| 107 | .map_err(loose::Error::ReadFileContents) | 92 | .and_then(|_| { |
| 108 | .and_then(|_| { | 93 | let relative_path = validated_path |
| 109 | let relative_path = validated_path | 94 | .strip_prefix(&self.ref_paths.base) |
| 110 | .strip_prefix(&self.ref_paths.base) | 95 | .expect("root contains path"); |
| 111 | .expect("root contains path"); | 96 | file::Reference::try_from_path(self.parent, name, &self.buf).map_err(|err| { |
| 112 | file::Reference::try_from_path(self.parent, relative_path, &self.buf).map_err(|err| { | 97 | loose::Error::ReferenceCreation { |
| 113 | loose::Error::ReferenceCreation { | 98 | err, |
| 114 | err, | 99 | relative_path: relative_path.into(), |
| 115 | relative_path: relative_path.into(), | 100 | } |
| 116 | } | ||
| 117 | }) | ||
| 118 | }) | 101 | }) |
| 119 | }) | 102 | }) |
| 103 | }) | ||
| 120 | }) | 104 | }) |
| 121 | } | 105 | } |
| 122 | } | 106 | } |
| @@ -21,9 +21,9 @@ impl Default for WriteReflog { · 20 unmodified lines | |||
| 21 | pub struct Reference<'a> { | 21 | pub struct Reference<'a> { |
| 22 | parent: &'a Store, | 22 | parent: &'a Store, |
| 23 | /// The path to uniquely identify this ref within its store. | 23 | /// The path to uniquely identify this ref within its store. |
| 24 | // TODO: make this a FullName(BString) and remove the `relative_path()` method entirely. | 24 | pub name: mutable::FullName, |
| 25 | relative_path: PathBuf, | 25 | /// The target of the reference, either a symbolic reference by full name or an object by its id. |
| 26 | target: mutable::Target, | 26 | pub target: mutable::Target, |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | /// A store for reference which uses plain files. | 29 | /// A store for reference which uses plain files. |
| @@ -3,7 +3,6 @@ use crate::{ · 2 unmodified lines | |||
| 3 | file::path_to_name, | 3 | file::path_to_name, |
| 4 | store::{file, packed}, | 4 | store::{file, packed}, |
| 5 | }; | 5 | }; |
| 6 | use bstr::BString; | ||
| 7 | use std::{ | 6 | use std::{ |
| 8 | cmp::Ordering, | 7 | cmp::Ordering, |
| 9 | io::Read, | 8 | io::Read, |
| @@ -27,19 +26,21 @@ impl<'p, 's> LooseThenPacked<'p, 's> { · 17 unmodified lines | |||
| 27 | }) | 26 | }) |
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | fn convert_loose(&mut self, res: std::io::Result<(PathBuf, Option<BString>)>) -> Result<Reference<'p, 's>, Error> { | 29 | fn convert_loose(&mut self, res: std::io::Result<(PathBuf, FullName)>) -> Result<Reference<'p, 's>, Error> { |
| 31 | let (refpath, _name) = res.map_err(Error::Traversal)?; | 30 | let (refpath, name) = res.map_err(Error::Traversal)?; |
| 32 | std::fs::File::open(&refpath) | 31 | std::fs::File::open(&refpath) |
| 33 | .and_then(|mut f| { | 32 | .and_then(|mut f| { |
| 34 | self.buf.clear(); | 33 | self.buf.clear(); |
| 35 | f.read_to_end(&mut self.buf) | 34 | f.read_to_end(&mut self.buf) |
| 36 | }) | 35 | }) |
| 37 | .map_err(Error::ReadFileContents)?; | 36 | .map_err(Error::ReadFileContents)?; |
| 38 | let relative_path = refpath.strip_prefix(&self.parent.base).expect("base contains path"); | 37 | file::Reference::try_from_path(self.parent, name, &self.buf) |
| 39 | file::Reference::try_from_path(self.parent, relative_path, &self.buf) | ||
| 40 | .map_err(|err| Error::ReferenceCreation { | 38 | .map_err(|err| Error::ReferenceCreation { |
| 41 | err, | 39 | err, |
| 42 | relative_path: relative_path.into(), | 40 | relative_path: refpath |
| 41 | .strip_prefix(&self.parent.base) | ||
| 42 | .expect("base contains path") | ||
| 43 | .into(), | ||
| 43 | }) | 44 | }) |
| 44 | .map(Reference::Loose) | 45 | .map(Reference::Loose) |
| 45 | } | 46 | } |
| @@ -60,8 +61,8 @@ impl<'p, 's> Iterator for LooseThenPacked<'p, 's> { · 14 unmodified lines | |||
| 60 | Some(self.convert_loose(res)) | 61 | Some(self.convert_loose(res)) |
| 61 | } | 62 | } |
| 62 | (Some(Ok(loose)), Some(Ok(packed))) => { | 63 | (Some(Ok(loose)), Some(Ok(packed))) => { |
| 63 | let loose_name = loose.1.as_ref().expect("name retrieval configured"); | 64 | let loose_name = loose.1.as_ref(); |
| 64 | match loose_name.as_slice().cmp(packed.full_name) { | 65 | match loose_name.cmp(packed.full_name) { |
| 65 | Ordering::Less => { | 66 | Ordering::Less => { |
| 66 | let res = self.loose.next().expect("name retrieval configured"); | 67 | let res = self.loose.next().expect("name retrieval configured"); |
| 67 | Some(self.convert_loose(res)) | 68 | Some(self.convert_loose(res)) |
| @@ -154,4 +155,5 @@ mod error { · 86 unmodified lines | |||
| 154 | } | 155 | } |
| 155 | } | 156 | } |
| 156 | 157 | ||
| 158 | use crate::mutable::FullName; | ||
| 157 | pub use error::Error; | 159 | pub use error::Error; |
| @@ -1,16 +1,14 @@ | |||
| 1 | use super::Reference; | 1 | use super::Reference; |
| 2 | use crate::{ | 2 | use crate::{ |
| 3 | mutable, | 3 | mutable, name, |
| 4 | store::{ | 4 | store::{ |
| 5 | file::{log, loose}, | 5 | file::{log, loose}, |
| 6 | packed, | 6 | packed, |
| 7 | }, | 7 | }, |
| 8 | FullName, | ||
| 8 | }; | 9 | }; |
| 9 | use git_hash::oid; | 10 | use git_hash::oid; |
| 10 | use std::{ | 11 | use std::convert::{TryFrom, TryInto}; |
| 11 | convert::{TryFrom, TryInto}, | ||
| 12 | path::Path, | ||
| 13 | }; | ||
| 14 | 12 | ||
| 15 | impl<'p, 's> TryFrom<Reference<'p, 's>> for crate::file::Reference<'s> { | 13 | impl<'p, 's> TryFrom<Reference<'p, 's>> for crate::file::Reference<'s> { |
| 16 | type Error = (); | 14 | type Error = (); |
| @@ -32,14 +30,6 @@ impl<'p, 's> Reference<'p, 's> { · 15 unmodified lines | |||
| 32 | } | 30 | } |
| 33 | } | 31 | } |
| 34 | 32 | ||
| 35 | /// Return the full name of this reference as path, only applicable if this is a loose reference. | ||
| 36 | pub fn relative_path(&self) -> Option<&Path> { | ||
| 37 | match self { | ||
| 38 | Reference::Loose(r) => Some(r.relative_path()), | ||
| 39 | Reference::Packed(_) => None, | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | /// For details, see [crate::file::Reference::peel_to_id_in_place]. | 33 | /// For details, see [crate::file::Reference::peel_to_id_in_place]. |
| 44 | pub fn peel_to_id_in_place( | 34 | pub fn peel_to_id_in_place( |
| 45 | &mut self, | 35 | &mut self, |
| @@ -96,7 +86,7 @@ impl<'p, 's> Reference<'p, 's> { · 50 unmodified lines | |||
| 96 | pub fn into_target(self) -> mutable::Target { | 86 | pub fn into_target(self) -> mutable::Target { |
| 97 | match self { | 87 | match self { |
| 98 | Reference::Packed(p) => mutable::Target::Peeled(p.object()), | 88 | Reference::Packed(p) => mutable::Target::Peeled(p.object()), |
| 99 | Reference::Loose(r) => r.into_target(), | 89 | Reference::Loose(r) => r.target, |
| 100 | } | 90 | } |
| 101 | } | 91 | } |
| 102 | 92 | ||
| @@ -109,10 +99,10 @@ impl<'p, 's> Reference<'p, 's> { · 6 unmodified lines | |||
| 109 | } | 99 | } |
| 110 | 100 | ||
| 111 | /// Return the full validated name of the reference. Please note that if the reference is packed, validation can fail here. | 101 | /// Return the full validated name of the reference. Please note that if the reference is packed, validation can fail here. |
| 112 | pub fn name(&self) -> Result<mutable::FullName, git_validate::refname::Error> { | 102 | pub fn name(&self) -> Result<FullName<'_>, name::Error> { |
| 113 | match self { | 103 | match self { |
| 114 | Reference::Packed(p) => p.full_name.try_into(), | 104 | Reference::Packed(p) => p.full_name.try_into(), |
| 115 | Reference::Loose(l) => Ok(l.name()), | 105 | Reference::Loose(l) => Ok(l.name.borrow()), |
| 116 | } | 106 | } |
| 117 | } | 107 | } |
| 118 | 108 | ||
| @@ -120,7 +110,7 @@ impl<'p, 's> Reference<'p, 's> { · 1 unmodified line | |||
| 120 | pub fn target(&self) -> mutable::Target { | 110 | pub fn target(&self) -> mutable::Target { |
| 121 | match self { | 111 | match self { |
| 122 | Reference::Packed(p) => mutable::Target::Peeled(p.target()), | 112 | Reference::Packed(p) => mutable::Target::Peeled(p.target()), |
| 123 | Reference::Loose(l) => l.target().to_owned(), | 113 | Reference::Loose(l) => l.target.clone(), |
| 124 | } | 114 | } |
| 125 | } | 115 | } |
| 126 | } | 116 | } |
| @@ -12,10 +12,7 @@ use nom::{ · 11 unmodified lines | |||
| 12 | IResult, | 12 | IResult, |
| 13 | }; | 13 | }; |
| 14 | use quick_error::quick_error; | 14 | use quick_error::quick_error; |
| 15 | use std::{ | 15 | use std::convert::{TryFrom, TryInto}; |
| 16 | convert::{TryFrom, TryInto}, | ||
| 17 | path::PathBuf, | ||
| 18 | }; | ||
| 19 | 16 | ||
| 20 | enum MaybeUnsafeState { | 17 | enum MaybeUnsafeState { |
| 21 | Id(ObjectId), | 18 | Id(ObjectId), |
| @@ -56,14 +53,10 @@ impl TryFrom<MaybeUnsafeState> for mutable::Target { · 34 unmodified lines | |||
| 56 | impl<'a> Reference<'a> { | 53 | impl<'a> Reference<'a> { |
| 57 | /// Create a new reference of the given `parent` store with `relative_path` service as unique identifier | 54 | /// Create a new reference of the given `parent` store with `relative_path` service as unique identifier |
| 58 | /// 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. |
| 59 | pub fn try_from_path( | 56 | pub fn try_from_path(parent: &'a Store, name: mutable::FullName, path_contents: &[u8]) -> Result<Self, Error> { |
| 60 | parent: &'a Store, | ||
| 61 | relative_path: impl Into<PathBuf>, | ||
| 62 | path_contents: &[u8], | ||
| 63 | ) -> Result<Self, Error> { | ||
| 64 | Ok(Reference { | 57 | Ok(Reference { |
| 65 | parent, | 58 | parent, |
| 66 | relative_path: relative_path.into(), | 59 | name, |
| 67 | target: parse(path_contents) | 60 | target: parse(path_contents) |
| 68 | .map_err(|_| Error::Parse(path_contents.into()))? | 61 | .map_err(|_| Error::Parse(path_contents.into()))? |
| 69 | .1 | 62 | .1 |
| @@ -1,8 +1,4 @@ | |||
| 1 | use crate::{ | 1 | use crate::store::file::{log, loose, Reference}; |
| 2 | store::file::{log, loose, Reference}, | ||
| 3 | FullName, | ||
| 4 | }; | ||
| 5 | use bstr::ByteSlice; | ||
| 6 | use std::io::Read; | 2 | use std::io::Read; |
| 7 | 3 | ||
| 8 | impl<'a> Reference<'a> { | 4 | impl<'a> Reference<'a> { |
| @@ -13,9 +9,7 @@ impl<'a> Reference<'a> { · 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. | 9 | /// 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 log_exists(&self) -> Result<bool, loose::reflog::Error> { | 10 | pub fn log_exists(&self) -> Result<bool, loose::reflog::Error> { |
| 15 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self | 11 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self |
| 16 | use os_str_bytes::OsStrBytes; | 12 | Ok(self.parent.reflog_path(self.name.borrow()).is_file()) |
| 17 | let name = self.relative_path.as_path().to_raw_bytes(); | ||
| 18 | Ok(self.parent.reflog_path(FullName(name.as_bstr())).is_file()) | ||
| 19 | } | 13 | } |
| 20 | /// Return a reflog reverse iterator for this ref, reading chunks from the back into the fixed buffer `buf`. | 14 | /// Return a reflog reverse iterator for this ref, reading chunks from the back into the fixed buffer `buf`. |
| 21 | /// | 15 | /// |
| @@ -26,9 +20,7 @@ impl<'a> Reference<'a> { · 4 unmodified lines | |||
| 26 | buf: &'b mut [u8], | 20 | buf: &'b mut [u8], |
| 27 | ) -> Result<Option<log::iter::Reverse<'b, std::fs::File>>, loose::reflog::Error> { | 21 | ) -> Result<Option<log::iter::Reverse<'b, std::fs::File>>, loose::reflog::Error> { |
| 28 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self | 22 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self |
| 29 | use os_str_bytes::OsStrBytes; | 23 | let file = match std::fs::File::open(self.parent.reflog_path(self.name.borrow())) { |
| 30 | let name = self.relative_path.as_path().to_raw_bytes(); | ||
| 31 | let file = match std::fs::File::open(self.parent.reflog_path(FullName(name.as_bstr()))) { | ||
| 32 | Ok(file) => file, | 24 | Ok(file) => file, |
| 33 | Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), | 25 | Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), |
| 34 | Err(err) => return Err(err.into()), | 26 | Err(err) => return Err(err.into()), |
| @@ -46,9 +38,7 @@ impl<'a> Reference<'a> { · 11 unmodified lines | |||
| 46 | ) -> Result<Option<impl Iterator<Item = Result<log::Line<'b>, log::iter::decode::Error>>>, loose::reflog::Error> | 38 | ) -> Result<Option<impl Iterator<Item = Result<log::Line<'b>, log::iter::decode::Error>>>, loose::reflog::Error> |
| 47 | { | 39 | { |
| 48 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self | 40 | // NOTE: Have to repeat the implementation of store::reflog_iter here as borrow_check believes impl Iterator binds self |
| 49 | use os_str_bytes::OsStrBytes; | 41 | match std::fs::File::open(self.parent.reflog_path(self.name.borrow())) { |
| 50 | let name = self.relative_path.as_path().to_raw_bytes(); | ||
| 51 | match std::fs::File::open(self.parent.reflog_path(FullName(name.as_bstr()))) { | ||
| 52 | Ok(mut file) => { | 42 | Ok(mut file) => { |
| 53 | buf.clear(); | 43 | buf.clear(); |
| 54 | file.read_to_end(buf)?; | 44 | file.read_to_end(buf)?; |
| @@ -1,45 +1,10 @@ | |||
| 1 | use crate::{file::Reference, mutable, mutable::FullName, Kind, Target}; | 1 | use crate::{file::Reference, Kind}; |
| 2 | use std::path::{Path, PathBuf}; | ||
| 3 | 2 | ||
| 4 | impl<'a> Reference<'a> { | 3 | impl<'a> Reference<'a> { |
| 5 | /// Return the kind of ref. | 4 | /// Return the kind of ref. |
| 6 | pub fn kind(&self) -> Kind { | 5 | pub fn kind(&self) -> Kind { |
| 7 | self.target.kind() | 6 | self.target.kind() |
| 8 | } | 7 | } |
| 9 | |||
| 10 | /// Return the target to which this instance is pointing. | ||
| 11 | pub fn target(&self) -> Target<'_> { | ||
| 12 | self.target.borrow() | ||
| 13 | } | ||
| 14 | |||
| 15 | /// Transform this reference into an owned `Target` | ||
| 16 | pub fn into_target(self) -> mutable::Target { | ||
| 17 | self.target | ||
| 18 | } | ||
| 19 | |||
| 20 | /// Return the full name of this reference as path. | ||
| 21 | /// | ||
| 22 | /// Use [`name()`][Reference::name()] if consistent component separators are required across platforms. | ||
| 23 | pub fn relative_path(&self) -> &Path { | ||
| 24 | &self.relative_path | ||
| 25 | } | ||
| 26 | |||
| 27 | /// Return our relative path while consuming this instance | ||
| 28 | pub fn into_relative_path(self) -> PathBuf { | ||
| 29 | self.relative_path | ||
| 30 | } | ||
| 31 | |||
| 32 | /// Return the full validated name of the reference | ||
| 33 | pub fn name(&self) -> FullName { | ||
| 34 | use os_str_bytes::OsStrBytes; | ||
| 35 | let name = self.relative_path.as_path().to_raw_bytes(); | ||
| 36 | #[cfg(windows)] | ||
| 37 | let name = { | ||
| 38 | use bstr::ByteSlice; | ||
| 39 | name.replace(b"\\", b"/") | ||
| 40 | }; | ||
| 41 | FullName(name.to_vec().into()) | ||
| 42 | } | ||
| 43 | } | 8 | } |
| 44 | 9 | ||
| 45 | mod logiter; | 10 | mod logiter; |
| @@ -98,10 +98,10 @@ pub mod to_id { · 97 unmodified lines | |||
| 98 | loose_then_packed::Reference::Loose(r) => r, | 98 | loose_then_packed::Reference::Loose(r) => r, |
| 99 | loose_then_packed::Reference::Packed(_) => unreachable!("handled above - we are done"), | 99 | loose_then_packed::Reference::Packed(_) => unreachable!("handled above - we are done"), |
| 100 | }; | 100 | }; |
| 101 | if seen.contains(&cursor.relative_path) { | 101 | if seen.contains(&cursor.name) { |
| 102 | return Err(Error::Cycle(cursor.parent.base.join(&cursor.relative_path))); | 102 | return Err(Error::Cycle(cursor.parent.base.join(cursor.name.to_path()))); |
| 103 | } | 103 | } |
| 104 | seen.insert(cursor.relative_path.clone()); | 104 | seen.insert(cursor.name.clone()); |
| 105 | count += 1; | 105 | count += 1; |
| 106 | const MAX_REF_DEPTH: usize = 5; | 106 | const MAX_REF_DEPTH: usize = 5; |
| 107 | if count == MAX_REF_DEPTH { | 107 | if count == MAX_REF_DEPTH { |
| @@ -60,8 +60,10 @@ impl<'a> Transaction<'a> { · 59 unmodified lines | |||
| 60 | .ref_contents(relative_path.as_ref()) | 60 | .ref_contents(relative_path.as_ref()) |
| 61 | .map_err(Error::from) | 61 | .map_err(Error::from) |
| 62 | .and_then(|opt| { | 62 | .and_then(|opt| { |
| 63 | opt.map(|buf| file::Reference::try_from_path(store, relative_path.as_ref(), &buf).map_err(Error::from)) | 63 | opt.map(|buf| { |
| 64 | .transpose() | 64 | file::Reference::try_from_path(store, change.update.name.clone(), &buf).map_err(Error::from) |
| 65 | }) | ||
| 66 | .transpose() | ||
| 65 | }) | 67 | }) |
| 66 | .or_else(|err| match err { | 68 | .or_else(|err| match err { |
| 67 | Error::ReferenceDecode(_) => Ok(None), | 69 | Error::ReferenceDecode(_) => Ok(None), |
| @@ -87,12 +89,12 @@ impl<'a> Transaction<'a> { · 19 unmodified lines | |||
| 87 | }) | 89 | }) |
| 88 | } | 90 | } |
| 89 | (Some(previous), Some(existing)) => { | 91 | (Some(previous), Some(existing)) => { |
| 90 | if !previous.is_null() && *previous != existing.target() { | 92 | if !previous.is_null() && *previous != existing.target { |
| 91 | let expected = previous.clone(); | 93 | let expected = previous.clone(); |
| 92 | return Err(Error::ReferenceOutOfDate { | 94 | return Err(Error::ReferenceOutOfDate { |
| 93 | full_name: change.name(), | 95 | full_name: change.name(), |
| 94 | expected, | 96 | expected, |
| 95 | actual: existing.target().to_owned(), | 97 | actual: existing.target.to_owned(), |
| 96 | }); | 98 | }); |
| 97 | } | 99 | } |
| 98 | } | 100 | } |
| @@ -100,7 +102,7 @@ impl<'a> Transaction<'a> { · 1 unmodified line | |||
| 100 | 102 | ||
| 101 | // Keep the previous value for the caller and ourselves. Maybe they want to keep a log of sorts. | 103 | // Keep the previous value for the caller and ourselves. Maybe they want to keep a log of sorts. |
| 102 | if let Some(existing) = existing_ref { | 104 | if let Some(existing) = existing_ref { |
| 103 | *previous = Some(existing.target().into()); | 105 | *previous = Some(existing.target.into()); |
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | lock | 108 | lock |
| @@ -120,11 +122,11 @@ impl<'a> Transaction<'a> { · 13 unmodified lines | |||
| 120 | 122 | ||
| 121 | let existing_ref = existing_ref?; | 123 | let existing_ref = existing_ref?; |
| 122 | match (&previous, &existing_ref) { | 124 | match (&previous, &existing_ref) { |
| 123 | (Create::Only, Some(existing)) if existing.target() != new.borrow() => { | 125 | (Create::Only, Some(existing)) if existing.target != new.borrow() => { |
| 124 | let new = new.clone(); | 126 | let new = new.clone(); |
| 125 | return Err(Error::MustNotExist { | 127 | return Err(Error::MustNotExist { |
| 126 | full_name: change.name(), | 128 | full_name: change.name(), |
| 127 | actual: existing.target().to_owned(), | 129 | actual: existing.target.to_owned(), |
| 128 | new, | 130 | new, |
| 129 | }); | 131 | }); |
| 130 | } | 132 | } |
| @@ -135,9 +137,9 @@ impl<'a> Transaction<'a> { · 4 unmodified lines | |||
| 135 | Some(existing), | 137 | Some(existing), |
| 136 | ) => match previous { | 138 | ) => match previous { |
| 137 | Target::Peeled(oid) if oid.is_null() => {} | 139 | Target::Peeled(oid) if oid.is_null() => {} |
| 138 | any_target if any_target.borrow() == existing.target() => {} | 140 | any_target if *any_target == existing.target => {} |
| 139 | _target_mismatch => { | 141 | _target_mismatch => { |
| 140 | let actual = existing.target().to_owned(); | 142 | let actual = existing.target.to_owned(); |
| 141 | let expected = previous.to_owned(); | 143 | let expected = previous.to_owned(); |
| 142 | let full_name = change.name(); | 144 | let full_name = change.name(); |
| 143 | return Err(Error::ReferenceOutOfDate { | 145 | return Err(Error::ReferenceOutOfDate { |
| @@ -163,7 +165,7 @@ impl<'a> Transaction<'a> { · 19 unmodified lines | |||
| 163 | *previous = match existing_ref { | 165 | *previous = match existing_ref { |
| 164 | None => Create::Only, | 166 | None => Create::Only, |
| 165 | Some(existing) => Create::OrUpdate { | 167 | Some(existing) => Create::OrUpdate { |
| 166 | previous: Some(existing.target().into()), | 168 | previous: Some(existing.target.into()), |
| 167 | }, | 169 | }, |
| 168 | }; | 170 | }; |
| 169 | 171 | ||
| @@ -4,7 +4,7 @@ mod reflog { · 3 unmodified lines | |||
| 4 | #[test] | 4 | #[test] |
| 5 | fn iter() -> crate::Result { | 5 | fn iter() -> crate::Result { |
| 6 | let store = file::store()?; | 6 | let store = file::store()?; |
| 7 | let r = store.find_existing("HEAD", None)?; | 7 | let r = store.loose_find_existing("HEAD")?; |
| 8 | let mut buf = Vec::new(); | 8 | let mut buf = Vec::new(); |
| 9 | assert_eq!(r.log_iter(&mut buf)?.expect("log exists").count(), 1); | 9 | assert_eq!(r.log_iter(&mut buf)?.expect("log exists").count(), 1); |
| 10 | Ok(()) | 10 | Ok(()) |
| @@ -13,7 +13,7 @@ mod reflog { · 2 unmodified lines | |||
| 13 | #[test] | 13 | #[test] |
| 14 | fn iter_rev() -> crate::Result { | 14 | fn iter_rev() -> crate::Result { |
| 15 | let store = file::store()?; | 15 | let store = file::store()?; |
| 16 | let r = store.find_existing("HEAD", None)?; | 16 | let r = store.loose_find_existing("HEAD")?; |
| 17 | let mut buf = [0u8; 256]; | 17 | let mut buf = [0u8; 256]; |
| 18 | assert_eq!(r.log_iter_rev(&mut buf)?.expect("log exists").count(), 1); | 18 | assert_eq!(r.log_iter_rev(&mut buf)?.expect("log exists").count(), 1); |
| 19 | Ok(()) | 19 | Ok(()) |
| @@ -21,11 +21,9 @@ mod reflog { · 1 unmodified line | |||
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | mod peel { | 23 | mod peel { |
| 24 | use crate::file; | 24 | use crate::{file, file::store_with_packed_refs}; |
| 25 | use crate::file::store_with_packed_refs; | ||
| 26 | use git_testtools::hex_to_id; | 25 | use git_testtools::hex_to_id; |
| 27 | use std::convert::TryFrom; | 26 | use std::convert::TryFrom; |
| 28 | use std::path::Path; | ||
| 29 | 27 | ||
| 30 | #[test] | 28 | #[test] |
| 31 | fn one_level() -> crate::Result { | 29 | fn one_level() -> crate::Result { |
| @@ -36,12 +34,12 @@ mod peel { · 4 unmodified lines | |||
| 36 | let nr = git_ref::file::Reference::try_from(r.peel_one_level(None).expect("exists").expect("no failure")) | 34 | let nr = git_ref::file::Reference::try_from(r.peel_one_level(None).expect("exists").expect("no failure")) |
| 37 | .expect("loose ref"); | 35 | .expect("loose ref"); |
| 38 | assert!( | 36 | assert!( |
| 39 | matches!(nr.target(), git_ref::Target::Peeled(_)), | 37 | matches!(nr.target.borrow(), git_ref::Target::Peeled(_)), |
| 40 | "iteration peels a single level" | 38 | "iteration peels a single level" |
| 41 | ); | 39 | ); |
| 42 | assert!(nr.peel_one_level(None).is_none(), "end of iteration"); | 40 | assert!(nr.peel_one_level(None).is_none(), "end of iteration"); |
| 43 | assert_eq!( | 41 | assert_eq!( |
| 44 | nr.target(), | 42 | nr.target.borrow(), |
| 45 | git_ref::Target::Peeled(&hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03")), | 43 | git_ref::Target::Peeled(&hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03")), |
| 46 | "we still have the peeled target" | 44 | "we still have the peeled target" |
| 47 | ); | 45 | ); |
| @@ -69,7 +67,7 @@ mod peel { · 21 unmodified lines | |||
| 69 | r.peel_to_id_in_place(None)?, | 67 | r.peel_to_id_in_place(None)?, |
| 70 | hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03") | 68 | hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03") |
| 71 | ); | 69 | ); |
| 72 | assert_eq!(r.relative_path(), Path::new("refs/remotes/origin/multi-link-target3")); | 70 | assert_eq!(r.name.as_ref(), "refs/remotes/origin/multi-link-target3"); |
| 73 | 71 | ||
| 74 | Ok(()) | 72 | Ok(()) |
| 75 | } | 73 | } |
| @@ -79,17 +77,13 @@ mod peel { · 3 unmodified lines | |||
| 79 | let store = file::store()?; | 77 | let store = file::store()?; |
| 80 | let mut r = store.loose_find_existing("loop-a")?; | 78 | let mut r = store.loose_find_existing("loop-a")?; |
| 81 | assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel"); | 79 | assert_eq!(r.kind(), git_ref::Kind::Symbolic, "there is something to peel"); |
| 82 | assert_eq!(r.relative_path(), Path::new("refs/loop-a")); | 80 | assert_eq!(r.name.as_ref(), "refs/loop-a"); |
| 83 | 81 | ||
| 84 | assert!(matches!( | 82 | assert!(matches!( |
| 85 | r.peel_to_id_in_place(None).unwrap_err(), | 83 | r.peel_to_id_in_place(None).unwrap_err(), |
| 86 | git_ref::file::reference::peel::to_id::Error::Cycle { .. } | 84 | git_ref::file::reference::peel::to_id::Error::Cycle { .. } |
| 87 | )); | 85 | )); |
| 88 | assert_eq!( | 86 | assert_eq!(r.name.as_ref(), "refs/loop-a", "the ref is not changed on error"); |
| 89 | r.relative_path(), | ||
| 90 | Path::new("refs/loop-a"), | ||
| 91 | "the ref is not changed on error" | ||
| 92 | ); | ||
| 93 | Ok(()) | 87 | Ok(()) |
| 94 | } | 88 | } |
| 95 | } | 89 | } |
| @@ -109,8 +103,14 @@ mod parse { · 13 unmodified lines | |||
| 109 | ($name:ident, $input:literal, $err:literal) => { | 103 | ($name:ident, $input:literal, $err:literal) => { |
| 110 | #[test] | 104 | #[test] |
| 111 | fn $name() { | 105 | fn $name() { |
| 106 | use std::convert::TryInto; | ||
| 112 | let store = store(); | 107 | let store = store(); |
| 113 | let err = Reference::try_from_path(&store, "name", $input).unwrap_err(); | 108 | let err = Reference::try_from_path( |
| 109 | &store, | ||
| 110 | "HEAD".try_into().expect("this is a valid name"), | ||
| 111 | $input, | ||
| 112 | ) | ||
| 113 | .unwrap_err(); | ||
| 114 | assert_eq!(err.to_string(), $err); | 114 | assert_eq!(err.to_string(), $err); |
| 115 | } | 115 | } |
| 116 | }; | 116 | }; |
| @@ -129,11 +129,17 @@ mod parse { · 12 unmodified lines | |||
| 129 | ($name:ident, $input:literal, $kind:path, $id:expr, $ref:expr) => { | 129 | ($name:ident, $input:literal, $kind:path, $id:expr, $ref:expr) => { |
| 130 | #[test] | 130 | #[test] |
| 131 | fn $name() { | 131 | fn $name() { |
| 132 | use std::convert::TryInto; | ||
| 132 | let store = store(); | 133 | let store = store(); |
| 133 | let reference = Reference::try_from_path(&store, "name", $input).unwrap(); | 134 | let reference = Reference::try_from_path( |
| 135 | &store, | ||
| 136 | "HEAD".try_into().expect("valid static name"), | ||
| 137 | $input, | ||
| 138 | ) | ||
| 139 | .unwrap(); | ||
| 134 | assert_eq!(reference.kind(), $kind); | 140 | assert_eq!(reference.kind(), $kind); |
| 135 | assert_eq!(reference.target().as_id(), $id); | 141 | assert_eq!(reference.target.borrow().as_id(), $id); |
| 136 | assert_eq!(reference.target().as_name(), $ref); | 142 | assert_eq!(reference.target.borrow().as_name(), $ref); |
| 137 | } | 143 | } |
| 138 | }; | 144 | }; |
| 139 | } | 145 | } |
| @@ -1,6 +1,5 @@ | |||
| 1 | use crate::file::{store, store_at}; | 1 | use crate::file::{store, store_at}; |
| 2 | use git_testtools::hex_to_id; | 2 | use git_testtools::hex_to_id; |
| 3 | use std::path::Path; | ||
| 4 | 3 | ||
| 5 | mod existing { | 4 | mod existing { |
| 6 | use crate::file::store; | 5 | use crate::file::store; |
| @@ -12,7 +11,7 @@ mod existing { · 5 unmodified lines | |||
| 12 | for (partial_name, expected_path) in &[("main", Some("refs/heads/main")), ("does-not-exist", None)] { | 11 | for (partial_name, expected_path) in &[("main", Some("refs/heads/main")), ("does-not-exist", None)] { |
| 13 | let reference = store.loose_find_existing(*partial_name); | 12 | let reference = store.loose_find_existing(*partial_name); |
| 14 | match expected_path { | 13 | match expected_path { |
| 15 | Some(expected_path) => assert_eq!(reference?.relative_path(), Path::new(expected_path)), | 14 | Some(expected_path) => assert_eq!(reference?.name.as_ref(), expected_path), |
| 16 | None => match reference { | 15 | None => match reference { |
| 17 | Ok(_) => panic!("Expected error"), | 16 | Ok(_) => panic!("Expected error"), |
| 18 | Err(git_ref::file::find::existing::Error::NotFound(name)) => { | 17 | Err(git_ref::file::find::existing::Error::NotFound(name)) => { |
| @@ -33,7 +32,7 @@ fn with_packed_refs() -> crate::Result { · 14 unmodified lines | |||
| 33 | let packed = store.packed()?; | 32 | let packed = store.packed()?; |
| 34 | let r = store.find_existing("main", packed.as_ref())?; | 33 | let r = store.find_existing("main", packed.as_ref())?; |
| 35 | assert_eq!(r.target().borrow().as_id().expect("peeled"), c1); | 34 | assert_eq!(r.target().borrow().as_id().expect("peeled"), c1); |
| 36 | assert_eq!(r.name().expect("valid name").as_ref(), "refs/heads/main"); | 35 | assert_eq!(r.name().expect("valid name").as_bstr(), "refs/heads/main"); |
| 37 | Ok(()) | 36 | Ok(()) |
| 38 | } | 37 | } |
| 39 | 38 | ||
| @@ -55,8 +54,8 @@ fn success() -> crate::Result { · 15 unmodified lines | |||
| 55 | ("refs/heads/main", "refs/heads/main", git_ref::Kind::Peeled), | 54 | ("refs/heads/main", "refs/heads/main", git_ref::Kind::Peeled), |
| 56 | ] { | 55 | ] { |
| 57 | let reference = store.loose_find(*partial_name)?.expect("exists"); | 56 | let reference = store.loose_find(*partial_name)?.expect("exists"); |
| 58 | assert_eq!(reference.relative_path(), Path::new(expected_path)); | 57 | assert_eq!(reference.name.as_bstr(), expected_path); |
| 59 | assert_eq!(reference.target().kind(), *expected_ref_kind); | 58 | assert_eq!(reference.target.borrow().kind(), *expected_ref_kind); |
| 60 | } | 59 | } |
| 61 | Ok(()) | 60 | Ok(()) |
| 62 | } | 61 | } |
| @@ -1,7 +1,7 @@ | |||
| 1 | use crate::file::{store, store_at, store_with_packed_refs}; | 1 | use crate::file::{store, store_at, store_with_packed_refs}; |
| 2 | use bstr::ByteSlice; | 2 | use bstr::ByteSlice; |
| 3 | use git_testtools::hex_to_id; | 3 | use git_testtools::hex_to_id; |
| 4 | use std::{convert::TryInto, path::PathBuf}; | 4 | use std::convert::TryInto; |
| 5 | 5 | ||
| 6 | #[test] | 6 | #[test] |
| 7 | fn no_packed_available_thus_no_iteration_possible() -> crate::Result { | 7 | fn no_packed_available_thus_no_iteration_possible() -> crate::Result { |
| @@ -47,7 +47,7 @@ fn loose_iter_with_broken_refs() -> crate::Result { · 39 unmodified lines | |||
| 47 | ); | 47 | ); |
| 48 | let ref_paths: Vec<_> = actual | 48 | let ref_paths: Vec<_> = actual |
| 49 | .drain(..first_error) | 49 | .drain(..first_error) |
| 50 | .filter_map(|e| e.ok().map(|e| e.into_relative_path())) | 50 | .filter_map(|e| e.ok().map(|e| e.name.into_inner())) |
| 51 | .collect(); | 51 | .collect(); |
| 52 | 52 | ||
| 53 | assert_eq!( | 53 | assert_eq!( |
| @@ -69,7 +69,7 @@ fn loose_iter_with_broken_refs() -> crate::Result { · 15 unmodified lines | |||
| 69 | "tags/t1" | 69 | "tags/t1" |
| 70 | ] | 70 | ] |
| 71 | .into_iter() | 71 | .into_iter() |
| 72 | .map(|p| PathBuf::from(format!("refs/{}", p))) | 72 | .map(|p| format!("refs/{}", p)) |
| 73 | .collect::<Vec<_>>(), | 73 | .collect::<Vec<_>>(), |
| 74 | "all paths are as expected" | 74 | "all paths are as expected" |
| 75 | ); | 75 | ); |
| @@ -100,7 +100,7 @@ fn loose_iter_with_prefix() -> crate::Result { · 24 unmodified lines | |||
| 100 | .collect::<Result<Vec<_>, _>>() | 100 | .collect::<Result<Vec<_>, _>>() |
| 101 | .expect("no broken ref in this subset") | 101 | .expect("no broken ref in this subset") |
| 102 | .into_iter() | 102 | .into_iter() |
| 103 | .map(|e| e.into_relative_path()) | 103 | .map(|e| e.name.into_inner()) |
| 104 | .collect::<Vec<_>>(); | 104 | .collect::<Vec<_>>(); |
| 105 | 105 | ||
| 106 | assert_eq!( | 106 | assert_eq!( |
| @@ -112,7 +112,7 @@ fn loose_iter_with_prefix() -> crate::Result { · 5 unmodified lines | |||
| 112 | "refs/heads/multi-link-target1", | 112 | "refs/heads/multi-link-target1", |
| 113 | ] | 113 | ] |
| 114 | .into_iter() | 114 | .into_iter() |
| 115 | .map(PathBuf::from) | 115 | .map(String::from) |
| 116 | .collect::<Vec<_>>(), | 116 | .collect::<Vec<_>>(), |
| 117 | "all paths are as expected" | 117 | "all paths are as expected" |
| 118 | ); | 118 | ); |
| @@ -129,7 +129,7 @@ fn overlay_iter() -> crate::Result { · 10 unmodified lines | |||
| 129 | .map(|r| { | 129 | .map(|r| { |
| 130 | r.map(|r| { | 130 | r.map(|r| { |
| 131 | ( | 131 | ( |
| 132 | r.name().expect("valid names only").into_inner(), | 132 | r.name().expect("valid names only").as_bstr().to_owned(), |
| 133 | r.target(), | 133 | r.target(), |
| 134 | r.is_packed(), | 134 | r.is_packed(), |
| 135 | ) | 135 | ) |
| @@ -185,7 +185,7 @@ fn overlay_prefixed_iter() -> crate::Result { · 49 unmodified lines | |||
| 185 | .map(|r| { | 185 | .map(|r| { |
| 186 | r.map(|r| { | 186 | r.map(|r| { |
| 187 | ( | 187 | ( |
| 188 | r.name().expect("valid names only").into_inner(), | 188 | r.name().expect("valid names only").as_bstr().to_owned(), |
| 189 | r.target(), | 189 | r.target(), |
| 190 | r.is_packed(), | 190 | r.is_packed(), |
| 191 | ) | 191 | ) |
| @@ -11,7 +11,7 @@ use git_ref::{ · 10 unmodified lines | |||
| 11 | transaction::{Change, Create, LogChange, RefEdit, RefLog}, | 11 | transaction::{Change, Create, LogChange, RefEdit, RefLog}, |
| 12 | }; | 12 | }; |
| 13 | use git_testtools::hex_to_id; | 13 | use git_testtools::hex_to_id; |
| 14 | use std::{convert::TryInto, path::Path}; | 14 | use std::convert::TryInto; |
| 15 | 15 | ||
| 16 | mod reference_with_equally_named { | 16 | mod reference_with_equally_named { |
| 17 | use crate::file::transaction::prepare_and_commit::{committer, empty_store}; | 17 | use crate::file::transaction::prepare_and_commit::{committer, empty_store}; |
| @@ -50,7 +50,7 @@ mod reference_with_equally_named { · 32 unmodified lines | |||
| 50 | if *is_empty { | 50 | if *is_empty { |
| 51 | let edits = edits?; | 51 | let edits = edits?; |
| 52 | assert!( | 52 | assert!( |
| 53 | store.find(edits[0].name.to_partial(), None)?.is_some(), | 53 | store.loose_find(edits[0].name.to_partial())?.is_some(), |
| 54 | "HEAD was created despite a directory being in the way" | 54 | "HEAD was created despite a directory being in the way" |
| 55 | ); | 55 | ); |
| 56 | } else { | 56 | } else { |
| @@ -108,8 +108,8 @@ fn reference_with_old_value_must_exist_when_creating_it() -> crate::Result { · 51 unmodified lines | |||
| 108 | #[test] | 108 | #[test] |
| 109 | fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Result { | 109 | fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Result { |
| 110 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; | 110 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; |
| 111 | let head = store.find("HEAD", None)?.expect("head exists already"); | 111 | let head = store.loose_find("HEAD")?.expect("head exists already"); |
| 112 | let target = head.target().to_owned(); | 112 | let target = head.target; |
| 113 | 113 | ||
| 114 | let err = store | 114 | let err = store |
| 115 | .transaction( | 115 | .transaction( |
| @@ -144,8 +144,8 @@ fn reference_with_explicit_value_must_match_the_value_on_update() -> crate::Resu · 28 unmodified lines | |||
| 144 | #[test] | 144 | #[test] |
| 145 | fn reference_with_create_only_must_not_exist_already_when_creating_it_if_the_value_does_not_match() -> crate::Result { | 145 | fn reference_with_create_only_must_not_exist_already_when_creating_it_if_the_value_does_not_match() -> crate::Result { |
| 146 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; | 146 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; |
| 147 | let head = store.find("HEAD", None)?.expect("head exists already"); | 147 | let head = store.loose_find("HEAD")?.expect("head exists already"); |
| 148 | let target = head.target().to_owned(); | 148 | let target = head.target; |
| 149 | 149 | ||
| 150 | let err = store | 150 | let err = store |
| 151 | .transaction( | 151 | .transaction( |
| @@ -178,8 +178,8 @@ fn reference_with_create_only_must_not_exist_already_when_creating_it_if_the_val · 26 unmodified lines | |||
| 178 | #[test] | 178 | #[test] |
| 179 | fn reference_with_create_only_must_not_exist_already_when_creating_it_unless_the_value_matches() -> crate::Result { | 179 | fn reference_with_create_only_must_not_exist_already_when_creating_it_unless_the_value_matches() -> crate::Result { |
| 180 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; | 180 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; |
| 181 | let head = store.find("HEAD", None)?.expect("head exists already"); | 181 | let head = store.loose_find("HEAD")?.expect("head exists already"); |
| 182 | let target = head.target().to_owned(); | 182 | let target = head.target; |
| 183 | let previous_reflog_count = reflog_lines(&store, "HEAD")?.len(); | 183 | let previous_reflog_count = reflog_lines(&store, "HEAD")?.len(); |
| 184 | 184 | ||
| 185 | let edits = store | 185 | let edits = store |
| @@ -258,7 +258,7 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 72 unmodified lines | |||
| 258 | let (_keep, mut store) = empty_store()?; | 258 | let (_keep, mut store) = empty_store()?; |
| 259 | store.write_reflog = *reflog_writemode; | 259 | store.write_reflog = *reflog_writemode; |
| 260 | let referent = "refs/heads/alt-main"; | 260 | let referent = "refs/heads/alt-main"; |
| 261 | assert!(store.find(referent, None)?.is_none(), "the reference does not exist"); | 261 | assert!(store.loose_find(referent)?.is_none(), "the reference does not exist"); |
| 262 | let log_ignored = LogChange { | 262 | let log_ignored = LogChange { |
| 263 | mode: RefLog::AndReference, | 263 | mode: RefLog::AndReference, |
| 264 | force_create_reflog: false, | 264 | force_create_reflog: false, |
| @@ -294,11 +294,11 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 29 unmodified lines | |||
| 294 | ); | 294 | ); |
| 295 | 295 | ||
| 296 | let head = store.loose_find_existing(edits[0].name.to_partial())?; | 296 | let head = store.loose_find_existing(edits[0].name.to_partial())?; |
| 297 | assert_eq!(head.relative_path(), Path::new("HEAD")); | 297 | assert_eq!(head.name.as_bstr(), "HEAD"); |
| 298 | assert_eq!(head.kind(), git_ref::Kind::Symbolic); | 298 | assert_eq!(head.kind(), git_ref::Kind::Symbolic); |
| 299 | assert_eq!(head.target().as_name(), Some(referent.as_bytes().as_bstr())); | 299 | assert_eq!(head.target.borrow().as_name(), Some(referent.as_bytes().as_bstr())); |
| 300 | assert!(!head.log_exists()?, "no reflog is written for symbolic ref"); | 300 | assert!(!head.log_exists()?, "no reflog is written for symbolic ref"); |
| 301 | assert!(store.find(referent, None)?.is_none(), "referent wasn't created"); | 301 | assert!(store.loose_find(referent)?.is_none(), "referent wasn't created"); |
| 302 | 302 | ||
| 303 | let new_oid = hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242"); | 303 | let new_oid = hex_to_id("28ce6a8b26aa170e1de65536fe8abe1832bd3242"); |
| 304 | let new = Target::Peeled(new_oid); | 304 | let new = Target::Peeled(new_oid); |
| @@ -360,7 +360,7 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 55 unmodified lines | |||
| 360 | "head is still symbolic, not detached" | 360 | "head is still symbolic, not detached" |
| 361 | ); | 361 | ); |
| 362 | assert_eq!( | 362 | assert_eq!( |
| 363 | head.target().as_name(), | 363 | head.target.borrow().as_name(), |
| 364 | Some(referent.as_bytes().as_bstr()), | 364 | Some(referent.as_bytes().as_bstr()), |
| 365 | "it still points to the referent" | 365 | "it still points to the referent" |
| 366 | ); | 366 | ); |
| @@ -368,7 +368,7 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 1 unmodified line | |||
| 368 | let referent_ref = store.loose_find_existing(referent)?; | 368 | let referent_ref = store.loose_find_existing(referent)?; |
| 369 | assert_eq!(referent_ref.kind(), git_ref::Kind::Peeled, "referent is a peeled ref"); | 369 | assert_eq!(referent_ref.kind(), git_ref::Kind::Peeled, "referent is a peeled ref"); |
| 370 | assert_eq!( | 370 | assert_eq!( |
| 371 | referent_ref.target().as_id(), | 371 | referent_ref.target.borrow().as_id(), |
| 372 | Some(new_oid.as_ref()), | 372 | Some(new_oid.as_ref()), |
| 373 | "referent points to desired hash" | 373 | "referent points to desired hash" |
| 374 | ); | 374 | ); |
| @@ -398,7 +398,7 @@ fn symbolic_head_missing_referent_then_update_referent() -> crate::Result { · 23 unmodified lines | |||
| 398 | fn write_reference_to_which_head_points_to_does_not_update_heads_reflog_even_though_it_should() -> crate::Result { | 398 | fn write_reference_to_which_head_points_to_does_not_update_heads_reflog_even_though_it_should() -> crate::Result { |
| 399 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; | 399 | let (_keep, store) = store_writable("make_repo_for_reflog.sh")?; |
| 400 | let head = store.loose_find_existing("HEAD")?; | 400 | let head = store.loose_find_existing("HEAD")?; |
| 401 | let referent = head.target().as_name().expect("symbolic ref").to_owned(); | 401 | let referent = head.target.borrow().as_name().expect("symbolic ref").to_owned(); |
| 402 | let previous_head_reflog = reflog_lines(&store, "HEAD")?; | 402 | let previous_head_reflog = reflog_lines(&store, "HEAD")?; |
| 403 | 403 | ||
| 404 | let new_id = hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc"); | 404 | let new_id = hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc"); |
| @@ -67,7 +67,7 @@ fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result { · 66 unmodified lines | |||
| 67 | previous: Some(Target::must_exist()), | 67 | previous: Some(Target::must_exist()), |
| 68 | log: RefLog::AndReference, | 68 | log: RefLog::AndReference, |
| 69 | }, | 69 | }, |
| 70 | name: head.name().into(), | 70 | name: head.name.clone(), |
| 71 | deref: false, | 71 | deref: false, |
| 72 | }), | 72 | }), |
| 73 | Fail::Immediately, | 73 | Fail::Immediately, |
| @@ -81,7 +81,7 @@ fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result { · 7 unmodified lines | |||
| 81 | previous: Some(Target::Symbolic("refs/heads/main".try_into()?)), | 81 | previous: Some(Target::Symbolic("refs/heads/main".try_into()?)), |
| 82 | log: RefLog::AndReference, | 82 | log: RefLog::AndReference, |
| 83 | }, | 83 | }, |
| 84 | name: head.name().into(), | 84 | name: head.name, |
| 85 | deref: false | 85 | deref: false |
| 86 | }], | 86 | }], |
| 87 | "the previous value was updated with the actual one" | 87 | "the previous value was updated with the actual one" |
| @@ -90,8 +90,8 @@ fn delete_ref_and_reflog_on_symbolic_no_deref() -> crate::Result { · 2 unmodified lines | |||
| 90 | store.reflog_iter_rev("HEAD", &mut [0u8; 128])?.is_none(), | 90 | store.reflog_iter_rev("HEAD", &mut [0u8; 128])?.is_none(), |
| 91 | "reflog was deleted" | 91 | "reflog was deleted" |
| 92 | ); | 92 | ); |
| 93 | assert!(store.find("HEAD", None)?.is_none(), "ref was deleted"); | 93 | assert!(store.loose_find("HEAD")?.is_none(), "ref was deleted"); |
| 94 | assert!(store.find("main", None)?.is_some(), "referent still exists"); | 94 | assert!(store.loose_find("main")?.is_some(), "referent still exists"); |
| 95 | Ok(()) | 95 | Ok(()) |
| 96 | } | 96 | } |
| 97 | 97 | ||
| @@ -108,7 +108,7 @@ fn delete_ref_with_incorrect_previous_value_fails() { · 10 unmodified lines | |||
| 108 | previous: Some(Target::Symbolic("refs/heads/main".try_into().unwrap())), | 108 | previous: Some(Target::Symbolic("refs/heads/main".try_into().unwrap())), |
| 109 | log: RefLog::Only, | 109 | log: RefLog::Only, |
| 110 | }, | 110 | }, |
| 111 | name: head.name().into(), | 111 | name: head.name.clone(), |
| 112 | deref: true, | 112 | deref: true, |
| 113 | }), | 113 | }), |
| 114 | Fail::Immediately, | 114 | Fail::Immediately, |
| @@ -118,9 +118,9 @@ fn delete_ref_with_incorrect_previous_value_fails() { · 3 unmodified lines | |||
| 118 | 118 | ||
| 119 | assert_eq!(err.to_string(), "The reference 'refs/heads/main' should have content ref: refs/heads/main, actual content was 02a7a22d90d7c02fb494ed25551850b868e634f0"); | 119 | assert_eq!(err.to_string(), "The reference 'refs/heads/main' should have content ref: refs/heads/main, actual content was 02a7a22d90d7c02fb494ed25551850b868e634f0"); |
| 120 | // everything stays as is | 120 | // everything stays as is |
| 121 | let head = store.find_existing("HEAD", None).unwrap(); | 121 | let head = store.loose_find_existing("HEAD").unwrap(); |
| 122 | assert!(head.log_exists().unwrap()); | 122 | assert!(head.log_exists().unwrap()); |
| 123 | let main = store.find_existing("main", None).expect("referent still exists"); | 123 | let main = store.loose_find_existing("main").expect("referent still exists"); |
| 124 | assert!(main.log_exists().unwrap()); | 124 | assert!(main.log_exists().unwrap()); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| @@ -137,7 +137,7 @@ fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result { · 10 unmodified lines | |||
| 137 | previous: Some(Target::Symbolic("refs/heads/main".try_into()?)), | 137 | previous: Some(Target::Symbolic("refs/heads/main".try_into()?)), |
| 138 | log: RefLog::Only, | 138 | log: RefLog::Only, |
| 139 | }, | 139 | }, |
| 140 | name: head.name().into(), | 140 | name: head.name, |
| 141 | deref: false, | 141 | deref: false, |
| 142 | }), | 142 | }), |
| 143 | Fail::Immediately, | 143 | Fail::Immediately, |
| @@ -145,12 +145,12 @@ fn delete_reflog_only_of_symbolic_no_deref() -> crate::Result { · 1 unmodified line | |||
| 145 | .commit(&committer())?; | 145 | .commit(&committer())?; |
| 146 | 146 | ||
| 147 | assert_eq!(edits.len(), 1); | 147 | assert_eq!(edits.len(), 1); |
| 148 | let head = store.find_existing("HEAD", None)?; | 148 | let head = store.loose_find_existing("HEAD")?; |
| 149 | assert!(!head.log_exists().unwrap()); | 149 | assert!(!head.log_exists().unwrap()); |
| 150 | let main = store.find_existing("main", None).expect("referent still exists"); | 150 | let main = store.loose_find_existing("main").expect("referent still exists"); |
| 151 | assert!(main.log_exists()?, "log is untouched, too"); | 151 | assert!(main.log_exists()?, "log is untouched, too"); |
| 152 | assert_eq!( | 152 | assert_eq!( |
| 153 | main.target(), | 153 | main.target, |
| 154 | head.peel_one_level(None).expect("a symref")?.target(), | 154 | head.peel_one_level(None).expect("a symref")?.target(), |
| 155 | "head points to main" | 155 | "head points to main" |
| 156 | ); | 156 | ); |
| @@ -170,7 +170,7 @@ fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result { · 13 unmodified lines | |||
| 170 | previous: Some(Target::must_exist()), | 170 | previous: Some(Target::must_exist()), |
| 171 | log: RefLog::Only, | 171 | log: RefLog::Only, |
| 172 | }, | 172 | }, |
| 173 | name: head.name().into(), | 173 | name: head.name, |
| 174 | deref: true, | 174 | deref: true, |
| 175 | }), | 175 | }), |
| 176 | Fail::Immediately, | 176 | Fail::Immediately, |
| @@ -178,12 +178,12 @@ fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result { · 1 unmodified line | |||
| 178 | .commit(&committer())?; | 178 | .commit(&committer())?; |
| 179 | 179 | ||
| 180 | assert_eq!(edits.len(), 2); | 180 | assert_eq!(edits.len(), 2); |
| 181 | let head = store.find_existing("HEAD", None)?; | 181 | let head = store.loose_find_existing("HEAD")?; |
| 182 | assert!(!head.log_exists()?); | 182 | assert!(!head.log_exists()?); |
| 183 | let main = store.find_existing("main", None).expect("referent still exists"); | 183 | let main = store.loose_find_existing("main").expect("referent still exists"); |
| 184 | assert!(!main.log_exists()?, "log is removed"); | 184 | assert!(!main.log_exists()?, "log is removed"); |
| 185 | assert_eq!( | 185 | assert_eq!( |
| 186 | main.target(), | 186 | main.target, |
| 187 | head.peel_one_level(None).expect("a symref")?.target(), | 187 | head.peel_one_level(None).expect("a symref")?.target(), |
| 188 | "head points to main" | 188 | "head points to main" |
| 189 | ); | 189 | ); |
| @@ -195,7 +195,7 @@ fn delete_reflog_only_of_symbolic_with_deref() -> crate::Result { · 5 unmodified lines | |||
| 195 | fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() { | 195 | fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() { |
| 196 | let (_keep, store) = empty_store().unwrap(); | 196 | let (_keep, store) = empty_store().unwrap(); |
| 197 | std::fs::write(store.base.join("HEAD"), &b"broken").unwrap(); | 197 | std::fs::write(store.base.join("HEAD"), &b"broken").unwrap(); |
| 198 | assert!(store.find("HEAD", None).is_err(), "the ref is truly broken"); | 198 | assert!(store.loose_find("HEAD").is_err(), "the ref is truly broken"); |
| 199 | 199 | ||
| 200 | let err = store | 200 | let err = store |
| 201 | .transaction( | 201 | .transaction( |
| @@ -222,7 +222,7 @@ fn delete_broken_ref_that_must_exist_fails_as_it_is_no_valid_ref() { · 20 unmodified lines | |||
| 222 | fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Result { | 222 | fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Result { |
| 223 | let (_keep, store) = empty_store()?; | 223 | let (_keep, store) = empty_store()?; |
| 224 | std::fs::write(store.base.join("HEAD"), &b"broken")?; | 224 | std::fs::write(store.base.join("HEAD"), &b"broken")?; |
| 225 | assert!(store.find("HEAD", None).is_err(), "the ref is truly broken"); | 225 | assert!(store.loose_find("HEAD").is_err(), "the ref is truly broken"); |
| 226 | 226 | ||
| 227 | let edits = store | 227 | let edits = store |
| 228 | .transaction( | 228 | .transaction( |
| @@ -238,7 +238,7 @@ fn delete_broken_ref_that_may_not_exist_works_even_in_deref_mode() -> crate::Res · 9 unmodified lines | |||
| 238 | ) | 238 | ) |
| 239 | .commit(&committer())?; | 239 | .commit(&committer())?; |
| 240 | 240 | ||
| 241 | assert!(store.find("HEAD", None)?.is_none(), "the ref was deleted"); | 241 | assert!(store.loose_find("HEAD")?.is_none(), "the ref was deleted"); |
| 242 | assert_eq!( | 242 | assert_eq!( |
| 243 | edits, | 243 | edits, |
| 244 | vec![RefEdit { | 244 | vec![RefEdit { |
| @@ -258,7 +258,7 @@ fn store_write_mode_has_no_effect_and_reflogs_are_always_deleted() -> crate::Res · 13 unmodified lines | |||
| 258 | for reflog_writemode in &[git_ref::file::WriteReflog::Normal, git_ref::file::WriteReflog::Disable] { | 258 | for reflog_writemode in &[git_ref::file::WriteReflog::Normal, git_ref::file::WriteReflog::Disable] { |
| 259 | let (_keep, mut store) = store_writable("make_repo_for_reflog.sh")?; | 259 | let (_keep, mut store) = store_writable("make_repo_for_reflog.sh")?; |
| 260 | store.write_reflog = *reflog_writemode; | 260 | store.write_reflog = *reflog_writemode; |
| 261 | assert!(store.find_existing("HEAD", None)?.log_exists()?,); | 261 | assert!(store.loose_find_existing("HEAD")?.log_exists()?,); |
| 262 | let edits = store | 262 | let edits = store |
| 263 | .transaction( | 263 | .transaction( |
| 264 | Some(RefEdit { | 264 | Some(RefEdit { |
| @@ -273,7 +273,7 @@ fn store_write_mode_has_no_effect_and_reflogs_are_always_deleted() -> crate::Res · 8 unmodified lines | |||
| 273 | ) | 273 | ) |
| 274 | .commit(&committer())?; | 274 | .commit(&committer())?; |
| 275 | assert_eq!(edits.len(), 1); | 275 | assert_eq!(edits.len(), 1); |
| 276 | assert!(!store.find_existing("HEAD", None)?.log_exists()?, "log was deleted"); | 276 | assert!(!store.loose_find_existing("HEAD")?.log_exists()?, "log was deleted"); |
| 277 | } | 277 | } |
| 278 | Ok(()) | 278 | Ok(()) |
| 279 | } | 279 | } |
| @@ -3,7 +3,7 @@ use crate::{ · 2 unmodified lines | |||
| 3 | packed::write_packed_refs_with, | 3 | packed::write_packed_refs_with, |
| 4 | }; | 4 | }; |
| 5 | use git_ref::{packed, PartialName}; | 5 | use git_ref::{packed, PartialName}; |
| 6 | use std::{convert::TryFrom, path::Path}; | 6 | use std::convert::TryFrom; |
| 7 | 7 | ||
| 8 | #[test] | 8 | #[test] |
| 9 | fn a_lock_file_would_not_be_a_valid_partial_name() { | 9 | fn a_lock_file_would_not_be_a_valid_partial_name() { |
| @@ -73,8 +73,8 @@ fn partial_name_to_full_name_conversion_rules_are_applied() -> crate::Result { · 63 unmodified lines | |||
| 73 | let packed = store.packed()?.expect("packed-refs exists"); | 73 | let packed = store.packed()?.expect("packed-refs exists"); |
| 74 | 74 | ||
| 75 | assert_eq!( | 75 | assert_eq!( |
| 76 | store.loose_find_existing("origin")?.relative_path(), | 76 | store.loose_find_existing("origin")?.name.as_bstr(), |
| 77 | Path::new("refs/remotes/origin/HEAD"), | 77 | "refs/remotes/origin/HEAD", |
| 78 | "a special that only applies to loose refs" | 78 | "a special that only applies to loose refs" |
| 79 | ); | 79 | ); |
| 80 | assert!( | 80 | assert!( |
| @@ -82,8 +82,8 @@ fn partial_name_to_full_name_conversion_rules_are_applied() -> crate::Result { · 1 unmodified line | |||
| 82 | "packed refs don't have this special case as they don't store HEADs or symrefs" | 82 | "packed refs don't have this special case as they don't store HEADs or symrefs" |
| 83 | ); | 83 | ); |
| 84 | assert_eq!( | 84 | assert_eq!( |
| 85 | store.loose_find_existing("HEAD")?.relative_path(), | 85 | store.loose_find_existing("HEAD")?.name.as_bstr(), |
| 86 | Path::new("HEAD"), | 86 | "HEAD", |
| 87 | "HEAD can be found in loose stores" | 87 | "HEAD can be found in loose stores" |
| 88 | ); | 88 | ); |
| 89 | assert!( | 89 | assert!( |
| @@ -9,8 +9,8 @@ quick_error! { · 8 unmodified lines | |||
| 9 | from() | 9 | from() |
| 10 | source(err) | 10 | source(err) |
| 11 | } | 11 | } |
| 12 | MisplacedHead(relative_path: PathBuf) { | 12 | MisplacedHead(name: crate::object::bstr::BString) { |
| 13 | display("Expected HEAD at '.git/HEAD', got '.git/{}'", relative_path.display()) | 13 | display("Expected HEAD at '.git/HEAD', got '.git/{}'", name) |
| 14 | } | 14 | } |
| 15 | MissingObjectsDirectory(missing: PathBuf) { | 15 | MissingObjectsDirectory(missing: PathBuf) { |
| 16 | display("Expected an objects directory at '{}'", missing.display()) | 16 | display("Expected an objects directory at '{}'", missing.display()) |
| @@ -42,8 +42,8 @@ pub fn is_git(git_dir: impl AsRef<Path>) -> Result<crate::Kind, Error> { · 25 unmodified lines | |||
| 42 | { | 42 | { |
| 43 | let refs = git_ref::file::Store::at(&dot_git, Default::default()); | 43 | let refs = git_ref::file::Store::at(&dot_git, Default::default()); |
| 44 | let head = refs.loose_find_existing("HEAD")?; | 44 | let head = refs.loose_find_existing("HEAD")?; |
| 45 | if head.relative_path() != Path::new("HEAD") { | 45 | if head.name().as_bstr() != "HEAD" { |
| 46 | return Err(Error::MisplacedHead(head.into_relative_path())); | 46 | return Err(Error::MisplacedHead(head.into_name().into_inner())); |
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||