refactor(tvix/cli): consistently assert type unity in known_paths

No situation should be allowed in which a path is inserted into
known_paths with different types twice, which we previously enforced
only for some path types.

Change-Id: I8cb47d4b29c0aab3c58694f8b590e131deba7043
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7843
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2023-01-16 16:36:32 +03:00 committed by tazjin
parent bf6f6a0b3f
commit 0cbdfffea2

View file

@ -50,39 +50,46 @@ impl Index<&str> for KnownPaths {
} }
impl KnownPaths { impl KnownPaths {
fn insert_path(&mut self, path: String, path_type: PathType) {
match self.paths.entry(path) {
hash_map::Entry::Vacant(entry) => {
entry.insert(path_type);
}
hash_map::Entry::Occupied(mut entry) => {
match (path_type, entry.get_mut()) {
// These variant combinations require no "merging action".
(PathType::Plain, PathType::Plain) => (),
(PathType::Output { .. }, PathType::Output { .. }) => (),
(
PathType::Derivation { output_names: new },
PathType::Derivation {
output_names: ref mut old,
},
) => {
old.extend(new);
}
_ => panic!("path '{}' inserted twice with different types", entry.key()),
};
}
};
}
/// Mark a plain path as known. /// Mark a plain path as known.
pub fn plain<S: ToString>(&mut self, path: S) { pub fn plain<S: ToString>(&mut self, path: S) {
self.paths.insert(path.to_string(), PathType::Plain); self.insert_path(path.to_string(), PathType::Plain);
} }
/// Mark a derivation as known. /// Mark a derivation as known.
pub fn drv<P: ToString, O: ToString>(&mut self, path: P, outputs: &[O]) { pub fn drv<P: ToString, O: ToString>(&mut self, path: P, outputs: &[O]) {
match self.paths.entry(path.to_string()) { self.insert_path(
hash_map::Entry::Occupied(mut entry) => { path.to_string(),
for output in outputs {
match entry.get_mut() {
PathType::Derivation { PathType::Derivation {
ref mut output_names, output_names: outputs.into_iter().map(ToString::to_string).collect(),
} => { },
output_names.insert(output.to_string()); );
}
// Branches like this explicitly panic right now to find odd
// situations where something unexpected is done with the
// same path being inserted twice as different types.
_ => panic!(
"bug: {} is already a known path, but not a derivation!",
path.to_string()
),
}
}
}
hash_map::Entry::Vacant(entry) => {
let output_names = outputs.iter().map(|o| o.to_string()).collect();
entry.insert(PathType::Derivation { output_names });
}
}
} }
/// Mark a derivation output path as known. /// Mark a derivation output path as known.
@ -92,27 +99,15 @@ impl KnownPaths {
name: N, name: N,
drv_path: D, drv_path: D,
) { ) {
match self.paths.entry(output_path.to_string()) { self.insert_path(
hash_map::Entry::Occupied(entry) => { output_path.to_string(),
/* nothing to do, really! */ PathType::Output {
debug_assert!(
*entry.get()
== PathType::Output {
name: name.to_string(), name: name.to_string(),
derivation: drv_path.to_string(), derivation: drv_path.to_string(),
} },
); );
} }
hash_map::Entry::Vacant(entry) => {
entry.insert(PathType::Output {
name: name.to_string(),
derivation: drv_path.to_string(),
});
}
}
}
/// Create a reference scanner from the current set of known paths. /// Create a reference scanner from the current set of known paths.
pub fn reference_scanner(&self) -> ReferenceScanner { pub fn reference_scanner(&self) -> ReferenceScanner {
let candidates = self.paths.keys().map(Clone::clone).collect(); let candidates = self.paths.keys().map(Clone::clone).collect();