Merge remote-tracking branch 'origin/fix/tree-entry-cmp'

* origin/fix/tree-entry-cmp:
  surf: fix comparison of tree entries

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
This commit is contained in:
Fintan Halpenny
2023-01-04 10:59:36 +00:00
2 changed files with 64 additions and 7 deletions
+38 -7
View File
@@ -36,14 +36,16 @@ use crate::{fs, object::commit};
pub struct Tree {
/// The object id of this tree.
id: Oid,
/// The first descendant entries for this tree.
entries: Vec<TreeEntry>,
/// The commit object that created this tree object.
commit: commit::Header,
}
impl Tree {
/// Creates a new tree.
pub(crate) fn new(id: Oid, entries: Vec<TreeEntry>, commit: commit::Header) -> Self {
/// Creates a new tree, ensuring the `entries` are sorted.
pub(crate) fn new(id: Oid, mut entries: Vec<TreeEntry>, commit: commit::Header) -> Self {
entries.sort();
Self {
id,
entries,
@@ -106,13 +108,40 @@ impl Serialize for Tree {
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Entry {
Tree(Oid),
Blob(Oid),
}
/// Entry in a Tree result.
impl PartialOrd for Entry {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Entry {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Entry::Tree(_), Entry::Tree(_)) => Ordering::Equal,
(Entry::Tree(_), Entry::Blob(_)) => Ordering::Less,
(Entry::Blob(_), Entry::Tree(_)) => Ordering::Greater,
(Entry::Blob(_), Entry::Blob(_)) => Ordering::Equal,
}
}
}
/// An entry that can be found in a tree.
///
/// Each entry consists of a [`TreeEntry::name`], its kind -- given as [`Entry`]
/// -- and the header of its associated [`TreeEntry::commit`].
///
/// # Ordering
///
/// The ordering of a `TreeEntry` is first by its [`Entry`] kind where
/// [`Entry::Tree`]s come before [`Entry::Blob`]. If both kinds are
/// equal then they are next compared by the lexicographical ordering
/// of their `name`s.
#[derive(Clone, Debug)]
pub struct TreeEntry {
name: String,
@@ -158,7 +187,9 @@ impl TreeEntry {
// To support `sort`.
impl Ord for TreeEntry {
fn cmp(&self, other: &Self) -> Ordering {
self.name.cmp(&other.name)
self.entry
.cmp(&other.entry)
.then(self.name.cmp(&other.name))
}
}
@@ -170,7 +201,7 @@ impl PartialOrd for TreeEntry {
impl PartialEq for TreeEntry {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
self.entry == other.entry && self.name == other.name
}
}
@@ -188,7 +219,7 @@ impl From<fs::Entry> for Entry {
#[cfg(feature = "serde")]
impl Serialize for TreeEntry {
/// Sample output:
/// ```
/// ```json
/// {
/// "kind": "blob",
/// "lastCommit": {
+26
View File
@@ -1,3 +1,5 @@
use std::path::PathBuf;
use git_ref_format::refname;
use radicle_surf::git::Repository;
use serde_json::json;
@@ -139,3 +141,27 @@ fn repo_blob() {
// Verify as_bytes.
assert_eq!(content.as_bytes().len(), content.size());
}
#[test]
fn tree_ordering() {
let repo = Repository::open(GIT_PLATINUM).unwrap();
let tree = repo
.tree(refname!("refs/heads/master"), &PathBuf::new())
.unwrap();
assert_eq!(
tree.entries()
.iter()
.map(|entry| entry.name().to_string())
.collect::<Vec<_>>(),
vec![
"bin".to_string(),
"special".to_string(),
"src".to_string(),
"text".to_string(),
"this".to_string(),
".i-am-well-hidden".to_string(),
".i-too-am-hidden".to_string(),
"README.md".to_string(),
]
);
}