History

alternate now handles cycles

Sebastian Thiel committed 6 years ago

Commit 71167e41 parent 73721183 files · +24 −5Browse files

Unified · Split

3 files
  1. git-odb/src/alternate.rs +7 −0
  2. git-odb/tests/alternate/mod.rs +14 −3
  3. tasks.md +3 −2
git-odb/src/alternate.rs+7−0
@@ -10,12 +10,19 @@ pub enum Error { · 9 unmodified lines
10 PathConversion(Vec<u8>),10 PathConversion(Vec<u8>),
11 #[error(transparent)]11 #[error(transparent)]
12 Init(#[from] compound::init::Error),12 Init(#[from] compound::init::Error),
13 #[error("Alternates form a cycle: {} -> {}", .0.iter().map(|p| format!("'{}'", p.display())).collect::<Vec<_>>().join(" -> "), .0.first().expect("more than one directories").display())]
14 Cycle(Vec<PathBuf>),
13}15}
14 16
15pub fn resolve(objects_directory: impl Into<PathBuf>) -> Result<Option<compound::Db>, Error> {17pub fn resolve(objects_directory: impl Into<PathBuf>) -> Result<Option<compound::Db>, Error> {
16 let mut dir = objects_directory.into();18 let mut dir = objects_directory.into();
17 let mut count = 0;19 let mut count = 0;
20 let mut seen = Vec::new();
18 loop {21 loop {
22 if seen.contains(&dir) {
23 break Err(Error::Cycle(seen));
24 }
25 seen.push(dir.clone());
19 let content = match fs::read(dir.join("info").join("alternates")) {26 let content = match fs::read(dir.join("info").join("alternates")) {
20 Ok(d) => d,27 Ok(d) => d,
21 Err(err) if err.kind() == io::ErrorKind::NotFound => {28 Err(err) if err.kind() == io::ErrorKind::NotFound => {
git-odb/tests/alternate/mod.rs+14−3
@@ -6,18 +6,29 @@ fn alternate(objects_at: impl Into<PathBuf>, objects_to: impl Into<PathBuf>) -> · 5 unmodified lines
6 let to = objects_to.into();6 let to = objects_to.into();
7 let at_info = at.join("info");7 let at_info = at.join("info");
8 fs::create_dir_all(&at_info)?;8 fs::create_dir_all(&at_info)?;
9 fs::create_dir(&to)?;9 fs::create_dir_all(&to)?;
10 fs::write(at_info.join("alternates"), to.to_string_lossy().as_bytes())?;10 fs::write(at_info.join("alternates"), to.to_string_lossy().as_bytes())?;
11 Ok((at, to))11 Ok((at, to))
12}12}
13 13
14#[test]14#[test]
15#[ignore]
16fn circular_alternates_are_detected() -> crate::Result {15fn circular_alternates_are_detected() -> crate::Result {
17 let tmp = tempdir::TempDir::new("alternates")?;16 let tmp = tempdir::TempDir::new("alternates")?;
18 alternate(tmp.path().join("a"), tmp.path().join("b"))?;17 let (from, _) = alternate(tmp.path().join("a"), tmp.path().join("b"))?;
19 alternate(tmp.path().join("b"), tmp.path().join("a"))?;18 alternate(tmp.path().join("b"), tmp.path().join("a"))?;
20 19
20 match alternate::resolve(&from) {
21 Err(alternate::Error::Cycle(chain)) => {
22 assert_eq!(
23 chain
24 .into_iter()
25 .map(|p| p.file_name().expect("non-root").to_str().expect("utf8").to_owned())
26 .collect::<Vec<_>>(),
27 vec!["a", "b"]
28 );
29 }
30 _ => unreachable!("should be a specific kind of error"),
31 }
21 Ok(())32 Ok(())
22}33}
23 34
tasks.md+3−2
@@ -9,9 +9,10 @@ · 8 unmodified lines
9 * [x] Add #![deny(rust_2018_idioms)] everywhere9 * [x] Add #![deny(rust_2018_idioms)] everywhere
10 * [x] Where 'thiserror' is available, use it for all Errors. It is more powerful, and if we paid for it already, let's use it.10 * [x] Where 'thiserror' is available, use it for all Errors. It is more powerful, and if we paid for it already, let's use it.
11 * [x] alternate DB (location - it's really must following the chain until a compound DB can be created)11 * [x] alternate DB (location - it's really must following the chain until a compound DB can be created)
12 * [ ] circular dependencies test12 * [x] circular dependencies test
13 * [ ] basic test13 * [x] basic test
14 * [ ] loose upgrade: jwalk powered iteration behind a feature flag14 * [ ] loose upgrade: jwalk powered iteration behind a feature flag
15 * [ ] full docs
15* **git-config**16* **git-config**
16 * A complete implementation, writing a the git remote configuration is needed for finalizing the clone17 * A complete implementation, writing a the git remote configuration is needed for finalizing the clone
17* **git-ref**18* **git-ref**