diff options
Diffstat (limited to 'vendor/gix-object/src/tree/mod.rs')
-rw-r--r-- | vendor/gix-object/src/tree/mod.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/gix-object/src/tree/mod.rs b/vendor/gix-object/src/tree/mod.rs new file mode 100644 index 000000000..688689c08 --- /dev/null +++ b/vendor/gix-object/src/tree/mod.rs @@ -0,0 +1,136 @@ +use std::cmp::Ordering; + +use crate::{ + bstr::{BStr, BString}, + tree, +}; + +mod ref_iter; +/// +pub mod write; + +/// The mode of items storable in a tree, similar to the file mode on a unix file system. +/// +/// Used in [mutable::Entry][crate::tree::Entry] and [EntryRef]. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)] +#[repr(u16)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub enum EntryMode { + /// A tree, or directory + Tree = 0o040000u16, + /// A file that is not executable + Blob = 0o100644, + /// A file that is executable + BlobExecutable = 0o100755, + /// A symbolic link + Link = 0o120000, + /// A commit of a git submodule + Commit = 0o160000, +} + +impl EntryMode { + /// Return true if this entry mode represents a Tree/directory + pub fn is_tree(&self) -> bool { + *self == EntryMode::Tree + } + + /// Return true if this entry mode represents anything BUT Tree/directory + pub fn is_no_tree(&self) -> bool { + *self != EntryMode::Tree + } + + /// Return true if the entry is any kind of blob. + pub fn is_blob(&self) -> bool { + matches!(self, EntryMode::Blob | EntryMode::BlobExecutable) + } + + /// Return true if the entry is any kind of blob or symlink. + pub fn is_blob_or_symlink(&self) -> bool { + matches!(self, EntryMode::Blob | EntryMode::BlobExecutable | EntryMode::Link) + } + + /// Represent the mode as descriptive string. + pub fn as_str(&self) -> &'static str { + use EntryMode::*; + match self { + Tree => "tree", + Blob => "blob", + BlobExecutable => "exe", + Link => "link", + Commit => "commit", + } + } +} + +/// An element of a [`TreeRef`][crate::TreeRef::entries]. +#[derive(PartialEq, Eq, Debug, Hash, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct EntryRef<'a> { + /// The kind of object to which `oid` is pointing. + pub mode: tree::EntryMode, + /// The name of the file in the parent tree. + pub filename: &'a BStr, + /// The id of the object representing the entry. + // TODO: figure out how these should be called. id or oid? It's inconsistent around the codebase. + // Answer: make it 'id', as in `git2` + #[cfg_attr(feature = "serde1", serde(borrow))] + pub oid: &'a gix_hash::oid, +} + +impl<'a> PartialOrd for EntryRef<'a> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl<'a> Ord for EntryRef<'a> { + /// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees. + /// Doing it like this is needed for compatibility with older, potentially broken(?) trees. + fn cmp(&self, other: &Self) -> Ordering { + let len = self.filename.len().min(other.filename.len()); + self.filename[..len].cmp(&other.filename[..len]) + } +} + +/// An entry in a [`Tree`][crate::Tree], similar to an entry in a directory. +#[derive(PartialEq, Eq, Debug, Hash, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Entry { + /// The kind of object to which `oid` is pointing to. + pub mode: EntryMode, + /// The name of the file in the parent tree. + pub filename: BString, + /// The id of the object representing the entry. + pub oid: gix_hash::ObjectId, +} + +impl PartialOrd for Entry { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for Entry { + /// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees. + fn cmp(&self, other: &Self) -> Ordering { + let common_len = self.filename.len().min(other.filename.len()); + self.filename[..common_len] + .cmp(&other.filename[..common_len]) + .then_with(|| self.filename.len().cmp(&other.filename.len())) + } +} + +/// Serialization +impl EntryMode { + /// Return the representation as used in the git internal format. + pub fn as_bytes(&self) -> &'static [u8] { + use EntryMode::*; + match self { + Tree => b"40000", + Blob => b"100644", + BlobExecutable => b"100755", + Link => b"120000", + Commit => b"160000", + } + } +} |