History

[ref] prefix iteration for all references

Sebastian Thiel committed 5 years ago

Commit 228ca001 parent aa6052a3 files · +104 −14Browse files

Showing the changes to git-ref/src/store (2 of 3 files). Show all

Unified · Split

2 files
  1. git-ref/src/store/file/loose/iter.rs +18 −6
  2. git-ref/src/store/file/overlay.rs +34 −1
git-ref/src/store/file/loose/iter.rs+18−6
@@ -141,18 +141,30 @@ impl file::Store { · 140 unmodified lines
141 ///141 ///
142 /// Otherwise it's similar to [`loose_iter()`][file::Store::loose_iter()].142 /// Otherwise it's similar to [`loose_iter()`][file::Store::loose_iter()].
143 pub fn loose_iter_prefixed(&self, prefix: impl AsRef<Path>) -> std::io::Result<Loose<'_>> {143 pub fn loose_iter_prefixed(&self, prefix: impl AsRef<Path>) -> std::io::Result<Loose<'_>> {
144 let prefix = prefix.as_ref();144 let prefix = self.validate_prefix(prefix.as_ref())?;
145 Ok(Loose::at_root(self, self.base.join(prefix), self.base.clone()))
146 }
147
148 pub(in crate::store::file) fn refs_dir(&self) -> PathBuf {
149 self.base.join("refs")
150 }
151 pub(in crate::store::file) fn validate_prefix<'a>(&self, prefix: &'a Path) -> std::io::Result<&'a Path> {
145 if prefix.is_absolute() {152 if prefix.is_absolute() {
146 return Err(std::io::Error::new(153 return Err(std::io::Error::new(
147 std::io::ErrorKind::InvalidInput,154 std::io::ErrorKind::InvalidInput,
148 "prefix must be a relative path, like 'refs/heads'",155 "prefix must be a relative path, like 'refs/heads'",
149 ));156 ));
150 }157 }
151 Ok(Loose::at_root(self, self.base.join(prefix), self.base.clone()))158 for component in prefix.components() {
152 }159 use std::path::Component::*;
153 160 if matches!(component, CurDir | ParentDir) {
154 pub(in crate::store::file) fn refs_dir(&self) -> PathBuf {161 return Err(std::io::Error::new(
155 self.base.join("refs")162 std::io::ErrorKind::InvalidInput,
163 "Refusing to handle prefixes with relative path components",
164 ));
165 }
166 }
167 Ok(prefix)
156 }168 }
157}169}
158 170
git-ref/src/store/file/overlay.rs+34−1
@@ -3,7 +3,13 @@ use crate::{ · 2 unmodified lines
3 store::{file, packed},3 store::{file, packed},
4};4};
5use bstr::BString;5use bstr::BString;
6use std::{cmp::Ordering, convert::TryInto, io::Read, iter::Peekable, path::PathBuf};6use std::{
7 cmp::Ordering,
8 convert::TryInto,
9 io::Read,
10 iter::Peekable,
11 path::{Path, PathBuf},
12};
7 13
8/// 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
9/// equivalent packed references.15/// equivalent packed references.
@@ -141,6 +147,32 @@ impl file::Store { · 131 unmodified lines
141 buf: Vec::new(),147 buf: Vec::new(),
142 })148 })
143 }149 }
150
151 /// As [`iter(…)`][file::Store::iter()], but filters by `prefix`, i.e. "refs/heads".
152 ///
153 /// Please note that "refs/heads` or "refs\\heads" is equivalent to "refs/heads/"
154 pub fn iter_prefixed<'p, 's>(
155 &'s self,
156 packed: &'p packed::Buffer,
157 prefix: impl AsRef<Path>,
158 ) -> std::io::Result<LooseThenPacked<'p, 's>> {
159 let prefix = self.validate_prefix(prefix.as_ref())?;
160 let packed_prefix = prefix.to_raw_bytes();
161 #[cfg(windows)]
162 let packed_prefix = packed_prefix.replace(b"\\", b"/");
163 #[cfg(not(windows))]
164 let packed_prefix = packed_prefix.into_owned();
165 Ok(LooseThenPacked {
166 parent: self,
167 packed: packed
168 .iter_prefixed(packed_prefix)
169 .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?
170 .peekable(),
171 loose: file::loose::iter::SortedLoosePaths::at_root_with_names(self.base.join(prefix), self.base.clone())
172 .peekable(),
173 buf: Vec::new(),
174 })
175 }
144}176}
145 177
146mod error {178mod error {
@@ -173,3 +205,4 @@ mod error { · 26 unmodified lines
173 }205 }
174}206}
175pub use error::Error;207pub use error::Error;
208use os_str_bytes::OsStrBytes;