summaryrefslogtreecommitdiffstats
path: root/vendor/gix-object/src/tree/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-object/src/tree/mod.rs')
-rw-r--r--vendor/gix-object/src/tree/mod.rs136
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",
+ }
+ }
+}