1use std::cmp::Ordering;
2
3use crate::{
4 bstr::{BStr, BString},
5 tree,
6};
7
8mod ref_iter;
9pub mod write;
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)]
16#[repr(u16)]
17#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
18pub enum EntryMode {
19 Tree = 0o040000u16,
21 Blob = 0o100644,
23 BlobExecutable = 0o100755,
25 Link = 0o120000,
27 Commit = 0o160000,
29}
30
31impl EntryMode {
32 pub fn is_tree(&self) -> bool {
34 *self == EntryMode::Tree
35 }
36
37 pub fn is_no_tree(&self) -> bool {
39 *self != EntryMode::Tree
40 }
41
42 pub fn is_blob(&self) -> bool {
44 matches!(self, EntryMode::Blob | EntryMode::BlobExecutable)
45 }
46
47 pub fn as_str(&self) -> &'static str {
49 use EntryMode::*;
50 match self {
51 Tree => "tree",
52 Blob => "blob",
53 BlobExecutable => "exe",
54 Link => "link",
55 Commit => "commit",
56 }
57 }
58}
59
60#[derive(PartialEq, Eq, Debug, Hash, Clone)]
62#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
63pub struct EntryRef<'a> {
64 pub mode: tree::EntryMode,
66 pub filename: &'a BStr,
68 #[cfg_attr(feature = "serde1", serde(borrow))]
72 pub oid: &'a git_hash::oid,
73}
74
75impl<'a> PartialOrd for EntryRef<'a> {
76 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77 Some(self.cmp(other))
78 }
79}
80
81impl<'a> Ord for EntryRef<'a> {
82 fn cmp(&self, other: &Self) -> Ordering {
84 let len = self.filename.len().min(other.filename.len());
85 self.filename[..len].cmp(&other.filename[..len])
86 }
87}
88
89#[derive(PartialEq, Eq, Debug, Hash, Clone)]
91#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
92pub struct Entry {
93 pub mode: EntryMode,
95 pub filename: BString,
97 pub oid: git_hash::ObjectId,
99}
100
101impl PartialOrd for Entry {
102 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
103 Some(self.cmp(other))
104 }
105}
106
107impl Ord for Entry {
108 fn cmp(&self, other: &Self) -> Ordering {
110 let common_len = self.filename.len().min(other.filename.len());
111 self.filename[..common_len]
112 .cmp(&other.filename[..common_len])
113 .then_with(|| self.filename.len().cmp(&other.filename.len()))
114 }
115}
116
117impl EntryMode {
119 pub fn as_bytes(&self) -> &'static [u8] {
121 use EntryMode::*;
122 match self {
123 Tree => b"40000",
124 Blob => b"100644",
125 BlobExecutable => b"100755",
126 Link => b"120000",
127 Commit => b"160000",
128 }
129 }
130}