tree_builder: when writing trees, rely on lexicographical order of RepoPath

This commit is contained in:
Yuya Nishihara 2023-05-31 19:30:48 +09:00
parent ae9f7aba52
commit 68a30c934d

View file

@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::collections::{BTreeMap, HashSet}; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use itertools::Itertools as _;
use crate::backend; use crate::backend;
use crate::backend::{TreeId, TreeValue}; use crate::backend::{TreeId, TreeValue};
use crate::repo_path::{RepoPath, RepoPathJoin}; use crate::repo_path::{RepoPath, RepoPathJoin};
@ -81,20 +83,13 @@ impl TreeBuilder {
} }
} }
// Write trees level by level, starting with trees without children. // Write trees in reverse lexicographical order, starting with trees without
// children.
let store = self.store.as_ref(); let store = self.store.as_ref();
loop { // TODO: trees_to_write.pop_last() can be used, but requires Rust 1.66.0
let mut dirs_to_write: HashSet<RepoPath> = trees_to_write.keys().cloned().collect(); let mut dirs_to_write = trees_to_write.keys().cloned().collect_vec();
while let Some(dir) = dirs_to_write.pop() {
for dir in trees_to_write.keys() {
if let Some(parent) = dir.parent() {
dirs_to_write.remove(&parent);
}
}
for dir in dirs_to_write {
let tree = trees_to_write.remove(&dir).unwrap(); let tree = trees_to_write.remove(&dir).unwrap();
if let Some((parent, basename)) = dir.split() { if let Some((parent, basename)) = dir.split() {
let parent_tree = trees_to_write.get_mut(&parent).unwrap(); let parent_tree = trees_to_write.get_mut(&parent).unwrap();
if tree.is_empty() { if tree.is_empty() {
@ -105,10 +100,12 @@ impl TreeBuilder {
} }
} else { } else {
// We're writing the root tree. Write it even if empty. Return its id. // We're writing the root tree. Write it even if empty. Return its id.
assert!(dirs_to_write.is_empty());
return store.write_tree(&dir, &tree).unwrap(); return store.write_tree(&dir, &tree).unwrap();
} }
} }
}
unreachable!("trees_to_write must contain the root tree");
} }
fn get_base_trees(&mut self) -> BTreeMap<RepoPath, backend::Tree> { fn get_base_trees(&mut self) -> BTreeMap<RepoPath, backend::Tree> {