Walk the history by commit time
Else it looks very funky when merges land
- Id
- 2b25a02d98a3a339f92c9d76c8b9801cb6d1965b
- Author
- Caio
- Commit time
- 2024-03-17T22:02:27+01:00
Modified urso/src/lib.rs
use std::{
borrow::Cow,
- collections::{HashSet, VecDeque},
+ collections::{BinaryHeap, HashSet},
path::{Path, PathBuf},
};
F: PathCommitVisitor,
{
let mut path = path.as_ref().to_path_buf();
+
let mut queue = OnceQueue::new();
- queue.insert(head);
+
+ {
+ let commit = self.find_commit(head)?;
+ let time = commit.time().expect("handle error");
+ queue.insert(ByCommitTime {
+ time,
+ id: commit.id,
+ });
+ }
let mut parent_ids = Vec::new();
let mut buf = Vec::new();
- while let Some(commit_id) = queue.remove() {
+ while let Some(info) = queue.remove() {
+ let ByCommitTime {
+ time: _,
+ id: commit_id,
+ } = info;
let commit = self.find_commit(commit_id)?;
let commit_tree = self.get_commit_tree(commit_id)?;
}
// single parent, follow it
1 => {
- queue.insert(parent_ids[0]);
+ {
+ let commit = self.find_commit(parent_ids[0])?;
+ let time = commit.time().expect("handle error");
+ queue.insert(ByCommitTime {
+ time,
+ id: commit.id,
+ });
+ }
parent_ids[0]
}
_merge_commit => {
if let Some(idx) = first_treesame_idx {
let parent_id = parent_ids[idx];
- queue.insert(parent_id);
+ {
+ let commit = self.find_commit(parent_id)?;
+ let time = commit.time().expect("handle error");
+ queue.insert(ByCommitTime {
+ time,
+ id: commit.id,
+ });
+ }
parent_id
} else {
for &id in parent_ids.iter() {
- queue.insert(id);
+ {
+ let commit = self.find_commit(id)?;
+ let time = commit.time().expect("handle error");
+ queue.insert(ByCommitTime {
+ time,
+ id: commit.id,
+ });
+ }
}
parent_ids[0]
}
}
}
-struct OnceQueue<T> {
- other: VecDeque<T>,
- seen: HashSet<T>,
+#[derive(Debug)]
+struct ByCommitTime {
+ time: Time,
+ id: ObjectId,
}
-impl<T: std::hash::Hash + Eq + Copy> OnceQueue<T> {
+impl PartialEq for ByCommitTime {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
+ }
+}
+
+impl Eq for ByCommitTime {}
+
+impl PartialOrd for ByCommitTime {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for ByCommitTime {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.time
+ .cmp(&other.time)
+ .then_with(|| self.id.cmp(&other.id))
+ }
+}
+
+struct OnceQueue {
+ items: BinaryHeap<ByCommitTime>,
+ seen: HashSet<ObjectId>,
+}
+
+impl OnceQueue {
pub(crate) fn new() -> Self {
Self {
- other: Default::default(),
+ items: Default::default(),
seen: Default::default(),
}
}
- pub(crate) fn insert(&mut self, info: T) -> bool {
- if self.seen.insert(info) {
- self.other.push_back(info);
+ pub(crate) fn insert(&mut self, info: ByCommitTime) -> bool {
+ if self.seen.insert(info.id) {
+ self.items.push(info);
true
} else {
false
}
}
- pub(crate) fn remove(&mut self) -> Option<T> {
- self.other.pop_front()
+ pub(crate) fn remove(&mut self) -> Option<ByCommitTime> {
+ self.items.pop()
}
}