History

prepare for multi-line parsing and all the bells and whistles

Sebastian Thiel committed 6 years ago

Commit 08f9ec41 parent 6dc57b36 files · +53 −28Browse files

Unified · Split

6 files
  1. README.md +3 −3
  2. git-odb/src/alternate.rs +22 −18
  3. git-odb/src/compound/init.rs +1 −3
  4. git-odb/src/compound/mod.rs +1 −1
  5. git-odb/tests/alternate/mod.rs +21 −3
  6. tasks.md +5 −0
README.md+3−3
@@ -91,9 +91,9 @@ become available. · 90 unmodified lines
9191 * **sink**
9292 * [x] write objects and obtain id
9393 * **alternates**
94− * [ ] _database that act as link to other known ODB types on disk_
95− * [ ] handles cycles
96− * [ ] handles recursive configurations
94+ * [ ] _database that act as link to other known git ODBs on disk_
95+ * [ ] safe with cycles and recursive configurations
96+ * [ ] multi-line with comments and quotes
9797 * **multi-odb**
9898 * [ ] _an ODB for object lookup from multiple lower level ODB at once_
9999 * **promisor**
git-odb/src/alternate.rs+22−18
@@ -14,31 +14,35 @@ pub enum Error { · 13 unmodified lines
1414 Cycle(Vec<PathBuf>),
1515 }
1616
17−pub fn resolve(objects_directory: impl Into<PathBuf>) -> Result<Option<compound::Db>, Error> {
18− let mut dir = objects_directory.into();
19− let mut count = 0;
17+pub fn resolve(objects_directory: impl Into<PathBuf>) -> Result<Vec<compound::Db>, Error> {
18+ let mut dirs = vec![(0, objects_directory.into())];
19+ let mut out = Vec::new();
2020 let mut seen = Vec::new();
21− loop {
21+ while let Some((depth, dir)) = dirs.pop() {
2222 if seen.contains(&dir) {
23− break Err(Error::Cycle(seen));
23+ return Err(Error::Cycle(seen));
2424 }
2525 seen.push(dir.clone());
26− let content = match fs::read(dir.join("info").join("alternates")) {
27− Ok(d) => d,
26+ match fs::read(dir.join("info").join("alternates")) {
27+ Ok(content) => {
28+ dirs.push((
29+ depth + 1,
30+ content
31+ .as_bstr()
32+ .to_path()
33+ .map(ToOwned::to_owned)
34+ .map_err(|_| Error::PathConversion(content))?,
35+ ));
36+ }
2837 Err(err) if err.kind() == io::ErrorKind::NotFound => {
29− break if count == 0 {
30− Ok(None)
31− } else {
32− Ok(Some(compound::Db::at(dir)?))
38+ // Only resolve for repositories with at least one link, otherwise the line below isn't safe to call
39+ if depth != 0 {
40+ // The tail of a chain doesn't have alternates, and thus is the real deal
41+ out.push(compound::Db::at(dir)?);
3342 }
3443 }
35− Err(err) => break Err(err.into()),
44+ Err(err) => return Err(err.into()),
3645 };
37− dir = content
38− .as_bstr()
39− .to_path()
40− .map(ToOwned::to_owned)
41− .map_err(|_| Error::PathConversion(content))?;
42− count += 1;
4346 }
47+ Ok(out)
4448 }
git-odb/src/compound/init.rs+1−3
@@ -35,9 +35,7 @@ impl compound::Db { · 34 unmodified lines
3535 Ok(compound::Db {
3636 loose: loose::Db::at(loose_objects.clone()),
3737 packs,
38− alternate: crate::alternate::resolve(loose_objects)
39− .map_err(Box::new)?
40− .map(Box::new),
38+ alternates: crate::alternate::resolve(loose_objects).map_err(Box::new)?,
4139 })
4240 }
4341 }
git-odb/src/compound/mod.rs+1−1
@@ -3,7 +3,7 @@ use crate::{loose, pack}; · 2 unmodified lines
33 pub struct Db {
44 pub loose: loose::Db,
55 pub packs: Vec<pack::Bundle>,
6− pub alternate: Option<Box<Db>>,
6+ pub alternates: Vec<Db>,
77 }
88
99 pub mod object {
git-odb/tests/alternate/mod.rs+21−3
@@ -2,12 +2,28 @@ use git_odb::alternate; · 1 unmodified line
22 use std::{fs, io, path::PathBuf};
33
44 fn alternate(objects_at: impl Into<PathBuf>, objects_to: impl Into<PathBuf>) -> Result<(PathBuf, PathBuf), io::Error> {
5+ alternate_with(objects_at, objects_to, None)
6+}
7+
8+fn alternate_with(
9+ objects_at: impl Into<PathBuf>,
10+ objects_to: impl Into<PathBuf>,
11+ content_before_to: Option<&str>,
12+) -> Result<(PathBuf, PathBuf), io::Error> {
513 let at = objects_at.into();
614 let to = objects_to.into();
715 let at_info = at.join("info");
816 fs::create_dir_all(&at_info)?;
917 fs::create_dir_all(&to)?;
10− fs::write(at_info.join("alternates"), to.to_string_lossy().as_bytes())?;
18+ let contents = if let Some(content) = content_before_to {
19+ let mut c = vec![b'\n'];
20+ c.extend(content.as_bytes());
21+ c.extend(to.to_string_lossy().as_bytes());
22+ c
23+ } else {
24+ to.to_string_lossy().as_bytes().to_owned()
25+ };
26+ fs::write(at_info.join("alternates"), contents)?;
1127 Ok((at, to))
1228 }
1329
@@ -38,13 +54,15 @@ fn single_link() -> crate::Result { · 24 unmodified lines
3854 let non_alternate = tmp.path().join("actual");
3955
4056 let (from, to) = alternate(tmp.path().join("a"), non_alternate)?;
41− assert_eq!(alternate::resolve(from).unwrap().unwrap().loose.path, to);
57+ let alternates = alternate::resolve(from)?;
58+ assert_eq!(alternates.len(), 1);
59+ assert_eq!(alternates[0].loose.path, to);
4260 Ok(())
4361 }
4462
4563 #[test]
4664 fn no_alternate_in_first_objects_dir() -> crate::Result {
4765 let tmp = tempdir::TempDir::new("alternates")?;
48− assert!(alternate::resolve(tmp.path()).unwrap().is_none());
66+ assert!(alternate::resolve(tmp.path())?.is_empty());
4967 Ok(())
5068 }
tasks.md+5−0
@@ -11,6 +11,11 @@ · 10 unmodified lines
1111 * [x] alternate DB (location - it's really must following the chain until a compound DB can be created)
1212 * [x] circular dependencies test
1313 * [x] basic test
14+ * [ ] are multiple alternates supported, too? YES
15+ * [ ] comments
16+ * [ ] quotes
17+ * [ ] support for relative directories
18+ * [ ] alternates lookup
1419 * [x] loose upgrade: jwalk powered iteration behind a feature flag
1520 * [ ] full docs
1621 * **git-config**