Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GitoxideLabs/gitoxide
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 943c6b6f95785c9a321e0aeeed910d47ad5e2091
Choose a base ref
..
head repository: GitoxideLabs/gitoxide
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 203d69c8890acc716bd4f7a7b1b2b91a8c828bde
Choose a head ref
Showing with 72 additions and 21 deletions.
  1. +1 −1 gix-diff/tests/tree/mod.rs
  2. +37 −15 gix-object/src/tree/mod.rs
  3. +8 −4 gix-object/src/tree/write.rs
  4. +26 −1 gix-object/tests/tree/mod.rs
2 changes: 1 addition & 1 deletion gix-diff/tests/tree/mod.rs
Original file line number Diff line number Diff line change
@@ -260,7 +260,7 @@ mod changes {
#[cfg(windows)]
let link_entry_oid = hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
#[cfg(windows)]
let link_entry_mode = EntryKind::Blob.into();
let link_entry_mode = EntryKind::Blob;
#[cfg(not(windows))]
let tree_with_link_id = hex_to_id("7e26dba59b6336f87d1d4ae3505a2da302b91c76");
#[cfg(not(windows))]
52 changes: 37 additions & 15 deletions gix-object/src/tree/mod.rs
Original file line number Diff line number Diff line change
@@ -48,6 +48,22 @@ impl From<EntryMode> for EntryKind {
}
}

/// Serialization
impl EntryKind {
/// Return the representation as used in the git internal format.
pub fn as_octal_str(&self) -> &'static BStr {
use EntryKind::*;
let bytes: &[u8] = match self {
Tree => b"40000",
Blob => b"100644",
BlobExecutable => b"100755",
Link => b"120000",
Commit => b"160000",
};
bytes.into()
}
}

impl std::ops::Deref for EntryMode {
type Target = u16;

@@ -122,6 +138,27 @@ impl EntryMode {
Commit => "commit",
}
}

/// Return the representation as used in the git internal format, which is octal and written
/// to the `backing` buffer. The respective sub-slice that was written to is returned.
pub fn as_bytes<'a>(&self, backing: &'a mut [u8; 6]) -> &'a BStr {
if self.0 == 0 {
std::slice::from_ref(&b'0')
} else {
let mut nb = 0;
let mut n = self.0;
while n > 0 {
let remainder = (n % 8) as u8;
backing[nb] = b'0' + remainder;
n /= 8;
nb += 1;
}
let res = &mut backing[..nb];
res.reverse();
res
}
.into()
}
}

/// An element of a [`TreeRef`][crate::TreeRef::entries].
@@ -186,18 +223,3 @@ impl Ord for Entry {
})
}
}

/// Serialization
impl EntryMode {
/// Return the representation as used in the git internal format.
pub fn as_bytes(&self) -> &'static [u8] {
use EntryKind::*;
match self.kind() {
Tree => b"40000",
Blob => b"100644",
BlobExecutable => b"100755",
Link => b"120000",
Commit => b"160000",
}
}
}
12 changes: 8 additions & 4 deletions gix-object/src/tree/write.rs
Original file line number Diff line number Diff line change
@@ -35,8 +35,9 @@ impl crate::WriteTo for Tree {
&self.entries,
"entries for serialization must be sorted by filename"
);
let mut buf = Default::default();
for Entry { mode, filename, oid } in &self.entries {
out.write_all(mode.as_bytes())?;
out.write_all(mode.as_bytes(&mut buf))?;
out.write_all(SPACE)?;

if filename.find_byte(b'\n').is_some() {
@@ -58,10 +59,11 @@ impl crate::WriteTo for Tree {
}

fn size(&self) -> u64 {
let mut buf = Default::default();
self.entries
.iter()
.map(|Entry { mode, filename, oid }| {
(mode.as_bytes().len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
(mode.as_bytes(&mut buf).len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
})
.sum()
}
@@ -80,8 +82,9 @@ impl<'a> crate::WriteTo for TreeRef<'a> {
&self.entries,
"entries for serialization must be sorted by filename"
);
let mut buf = Default::default();
for EntryRef { mode, filename, oid } in &self.entries {
out.write_all(mode.as_bytes())?;
out.write_all(mode.as_bytes(&mut buf))?;
out.write_all(SPACE)?;

if filename.find_byte(b'\n').is_some() {
@@ -103,10 +106,11 @@ impl<'a> crate::WriteTo for TreeRef<'a> {
}

fn size(&self) -> u64 {
let mut buf = Default::default();
self.entries
.iter()
.map(|EntryRef { mode, filename, oid }| {
(mode.as_bytes().len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
(mode.as_bytes(&mut buf).len() + 1 + filename.len() + 1 + oid.as_bytes().len()) as u64
})
.sum()
}
27 changes: 26 additions & 1 deletion gix-object/tests/tree/mod.rs
Original file line number Diff line number Diff line change
@@ -199,7 +199,7 @@ mod entries {
}

mod entry_mode {
use gix_object::tree::EntryMode;
use gix_object::tree::{EntryKind, EntryMode};

#[test]
fn size_in_bytes() {
@@ -209,4 +209,29 @@ mod entry_mode {
"it should not change without notice"
);
}

#[test]
fn as_bytes() {
let mut buf = Default::default();
for (mode, expected) in [
(EntryMode::from(EntryKind::Tree), EntryKind::Tree.as_octal_str()),
(EntryKind::Blob.into(), EntryKind::Blob.as_octal_str()),
(
EntryKind::BlobExecutable.into(),
EntryKind::BlobExecutable.as_octal_str(),
),
(EntryKind::Link.into(), EntryKind::Link.as_octal_str()),
(EntryKind::Commit.into(), EntryKind::Commit.as_octal_str()),
(
EntryMode::try_from(b"100744 ".as_ref()).expect("valid"),
"100744".into(),
),
(
EntryMode::try_from(b"100644 ".as_ref()).expect("valid"),
"100644".into(),
),
] {
assert_eq!(mode.as_bytes(&mut buf), expected)
}
}
}