Skip to content

Commit e3b146f

Browse files
committed
Merge branch 'fix-848'
2 parents a849da8 + ca37915 commit e3b146f

File tree

15 files changed

+189
-158
lines changed

15 files changed

+189
-158
lines changed

gix-object/src/tree/mod.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub struct EntryRef<'a> {
7272
pub filename: &'a BStr,
7373
/// The id of the object representing the entry.
7474
// TODO: figure out how these should be called. id or oid? It's inconsistent around the codebase.
75-
// Answer: make it 'id', as in `git2`
75+
// Answer: make it 'id', as in `git2`
7676
#[cfg_attr(feature = "serde", serde(borrow))]
7777
pub oid: &'a gix_hash::oid,
7878
}
@@ -84,11 +84,14 @@ impl<'a> PartialOrd for EntryRef<'a> {
8484
}
8585

8686
impl<'a> Ord for EntryRef<'a> {
87-
/// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees.
88-
/// Doing it like this is needed for compatibility with older, potentially broken(?) trees.
89-
fn cmp(&self, other: &Self) -> Ordering {
90-
let len = self.filename.len().min(other.filename.len());
91-
self.filename[..len].cmp(&other.filename[..len])
87+
fn cmp(&self, b: &Self) -> Ordering {
88+
let a = self;
89+
let common = a.filename.len().min(b.filename.len());
90+
a.filename[..common].cmp(&b.filename[..common]).then_with(|| {
91+
let a = a.filename.get(common).or_else(|| a.mode.is_tree().then_some(&b'/'));
92+
let b = b.filename.get(common).or_else(|| b.mode.is_tree().then_some(&b'/'));
93+
a.cmp(&b)
94+
})
9295
}
9396
}
9497

@@ -111,12 +114,14 @@ impl PartialOrd for Entry {
111114
}
112115

113116
impl Ord for Entry {
114-
/// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees.
115-
fn cmp(&self, other: &Self) -> Ordering {
116-
let common_len = self.filename.len().min(other.filename.len());
117-
self.filename[..common_len]
118-
.cmp(&other.filename[..common_len])
119-
.then_with(|| self.filename.len().cmp(&other.filename.len()))
117+
fn cmp(&self, b: &Self) -> Ordering {
118+
let a = self;
119+
let common = a.filename.len().min(b.filename.len());
120+
a.filename[..common].cmp(&b.filename[..common]).then_with(|| {
121+
let a = a.filename.get(common).or_else(|| a.mode.is_tree().then_some(&b'/'));
122+
let b = b.filename.get(common).or_else(|| b.mode.is_tree().then_some(&b'/'));
123+
a.cmp(&b)
124+
})
120125
}
121126
}
122127

gix-object/src/tree/write.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,16 @@ impl crate::WriteTo for Tree {
5353
Ok(())
5454
}
5555

56+
fn kind(&self) -> Kind {
57+
Kind::Tree
58+
}
59+
5660
fn size(&self) -> usize {
5761
self.entries
5862
.iter()
5963
.map(|Entry { mode, filename, oid }| mode.as_bytes().len() + 1 + filename.len() + 1 + oid.as_bytes().len())
6064
.sum()
6165
}
62-
63-
fn kind(&self) -> Kind {
64-
Kind::Tree
65-
}
6666
}
6767

6868
/// Serialization
@@ -96,6 +96,10 @@ impl<'a> crate::WriteTo for TreeRef<'a> {
9696
Ok(())
9797
}
9898

99+
fn kind(&self) -> Kind {
100+
Kind::Tree
101+
}
102+
99103
fn size(&self) -> usize {
100104
self.entries
101105
.iter()
@@ -104,8 +108,4 @@ impl<'a> crate::WriteTo for TreeRef<'a> {
104108
})
105109
.sum()
106110
}
107-
108-
fn kind(&self) -> Kind {
109-
Kind::Tree
110-
}
111111
}

gix-object/tests/immutable/commit/from_bytes.rs renamed to gix-object/tests/commit/from_bytes.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use gix_actor::{Sign, SignatureRef, Time};
22
use gix_object::{bstr::ByteSlice, commit::message::body::TrailerRef, CommitRef};
33
use smallvec::SmallVec;
44

5-
use crate::immutable::{
5+
use crate::{
66
commit::{LONG_MESSAGE, MERGE_TAG, SIGNATURE},
7-
fixture_bytes, linus_signature, signature,
7+
fixture_name, linus_signature, signature,
88
};
99

1010
#[test]
1111
fn unsigned() -> crate::Result {
1212
assert_eq!(
13-
CommitRef::from_bytes(&fixture_bytes("commit", "unsigned.txt"))?,
13+
CommitRef::from_bytes(&fixture_name("commit", "unsigned.txt"))?,
1414
CommitRef {
1515
tree: b"1b2dfb4ac5e42080b682fc676e9738c94ce6d54d".as_bstr(),
1616
parents: SmallVec::default(),
@@ -27,7 +27,7 @@ fn unsigned() -> crate::Result {
2727
#[test]
2828
fn whitespace() -> crate::Result {
2929
assert_eq!(
30-
CommitRef::from_bytes(&fixture_bytes("commit", "whitespace.txt"))?,
30+
CommitRef::from_bytes(&fixture_name("commit", "whitespace.txt"))?,
3131
CommitRef {
3232
tree: b"9bed6275068a0575243ba8409253e61af81ab2ff".as_bstr(),
3333
parents: SmallVec::from(vec![b"26b4df046d1776c123ac69d918f5aec247b58cc6".as_bstr()]),
@@ -44,7 +44,7 @@ fn whitespace() -> crate::Result {
4444
#[test]
4545
fn signed_singleline() -> crate::Result {
4646
assert_eq!(
47-
CommitRef::from_bytes(&fixture_bytes("commit", "signed-singleline.txt"))?,
47+
CommitRef::from_bytes(&fixture_name("commit", "signed-singleline.txt"))?,
4848
CommitRef {
4949
tree: b"00fc39317701176e326974ce44f5bd545a32ec0b".as_bstr(),
5050
parents: SmallVec::from(vec![b"09d8d3a12e161a7f6afb522dbe8900a9c09bce06".as_bstr()]),
@@ -60,7 +60,7 @@ fn signed_singleline() -> crate::Result {
6060

6161
#[test]
6262
fn mergetag() -> crate::Result {
63-
let fixture = fixture_bytes("commit", "mergetag.txt");
63+
let fixture = fixture_name("commit", "mergetag.txt");
6464
let commit = CommitRef {
6565
tree: b"1c61918031bf2c7fab9e17dde3c52a6a9884fcb5".as_bstr(),
6666
parents: SmallVec::from(vec![
@@ -85,7 +85,7 @@ fn mergetag() -> crate::Result {
8585
#[test]
8686
fn signed() -> crate::Result {
8787
assert_eq!(
88-
CommitRef::from_bytes(&fixture_bytes("commit", "signed.txt"))?,
88+
CommitRef::from_bytes(&fixture_name("commit", "signed.txt"))?,
8989
CommitRef {
9090
tree: b"00fc39317701176e326974ce44f5bd545a32ec0b".as_bstr(),
9191
parents: SmallVec::from(vec![b"09d8d3a12e161a7f6afb522dbe8900a9c09bce06".as_bstr()]),
@@ -102,7 +102,7 @@ fn signed() -> crate::Result {
102102
#[test]
103103
fn signed_with_encoding() -> crate::Result {
104104
assert_eq!(
105-
CommitRef::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt"))?,
105+
CommitRef::from_bytes(&fixture_name("commit", "signed-with-encoding.txt"))?,
106106
CommitRef {
107107
tree: b"1973afa74d87b2bb73fa884aaaa8752aec43ea88".as_bstr(),
108108
parents: SmallVec::from(vec![b"79c51cc86923e2b8ca0ee5c4eb75e48027133f9a".as_bstr()]),
@@ -119,7 +119,7 @@ fn signed_with_encoding() -> crate::Result {
119119
#[test]
120120
fn with_encoding() -> crate::Result {
121121
assert_eq!(
122-
CommitRef::from_bytes(&fixture_bytes("commit", "with-encoding.txt"))?,
122+
CommitRef::from_bytes(&fixture_name("commit", "with-encoding.txt"))?,
123123
CommitRef {
124124
tree: b"4a1c03029e7407c0afe9fc0320b3258e188b115e".as_bstr(),
125125
parents: SmallVec::from(vec![b"7ca98aad461a5c302cb4c9e3acaaa6053cc67a62".as_bstr()]),
@@ -144,7 +144,7 @@ fn with_trailer() -> crate::Result {
144144
sign: Sign::Plus,
145145
},
146146
};
147-
let backing = fixture_bytes("commit", "message-with-footer.txt");
147+
let backing = fixture_name("commit", "message-with-footer.txt");
148148
let commit = CommitRef::from_bytes(&backing)?;
149149
assert_eq!(
150150
commit,
@@ -224,7 +224,7 @@ instead of depending directly on the lower-level crates.
224224
#[test]
225225
fn merge() -> crate::Result {
226226
assert_eq!(
227-
CommitRef::from_bytes(&fixture_bytes("commit", "merge.txt"))?,
227+
CommitRef::from_bytes(&fixture_name("commit", "merge.txt"))?,
228228
CommitRef {
229229
tree: b"0cf16ce8e229b59a761198975f0c0263229faf82".as_bstr(),
230230
parents: SmallVec::from(vec![
@@ -255,7 +255,7 @@ iyBBl69jASy41Ug/BlFJbw4+ItkShpXwkJKuBBV/JExChmvbxYWaS7QnyYC9UO0=
255255

256256
#[test]
257257
fn newline_right_after_signature_multiline_header() -> crate::Result {
258-
let fixture = fixture_bytes("commit", "signed-whitespace.txt");
258+
let fixture = fixture_name("commit", "signed-whitespace.txt");
259259
let commit = CommitRef::from_bytes(&fixture)?;
260260
let pgp_sig = OTHER_SIGNATURE.as_bstr();
261261
assert_eq!(commit.extra_headers[0].1.as_ref(), pgp_sig);

gix-object/tests/immutable/commit/iter.rs renamed to gix-object/tests/commit/iter.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
use gix_object::{bstr::ByteSlice, commit::ref_iter::Token, CommitRefIter};
22

33
use crate::{
4-
hex_to_id,
5-
immutable::{
6-
commit::{LONG_MESSAGE, MERGE_TAG, SIGNATURE},
7-
fixture_bytes, linus_signature, signature,
8-
},
4+
commit::{LONG_MESSAGE, MERGE_TAG, SIGNATURE},
5+
fixture_name, hex_to_id, linus_signature, signature,
96
};
107

118
#[test]
129
fn newline_right_after_signature_multiline_header() -> crate::Result {
13-
let data = fixture_bytes("commit", "signed-whitespace.txt");
10+
let data = fixture_name("commit", "signed-whitespace.txt");
1411
let tokens = CommitRefIter::from_bytes(&data).collect::<Result<Vec<_>, _>>()?;
1512
assert_eq!(tokens.len(), 7, "mainly a parsing exercise");
1613
match tokens.last().expect("there are tokens") {
@@ -24,7 +21,7 @@ fn newline_right_after_signature_multiline_header() -> crate::Result {
2421

2522
#[test]
2623
fn signed_with_encoding() -> crate::Result {
27-
let input = fixture_bytes("commit", "signed-with-encoding.txt");
24+
let input = fixture_name("commit", "signed-with-encoding.txt");
2825
let iter = CommitRefIter::from_bytes(&input);
2926
assert_eq!(
3027
iter.collect::<Result<Vec<_>, _>>()?,
@@ -55,7 +52,7 @@ fn signed_with_encoding() -> crate::Result {
5552
#[test]
5653
fn whitespace() -> crate::Result {
5754
assert_eq!(
58-
CommitRefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::<Result<Vec<_>, _>>()?,
55+
CommitRefIter::from_bytes(&fixture_name("commit", "whitespace.txt")).collect::<Result<Vec<_>, _>>()?,
5956
vec![
6057
Token::Tree {
6158
id: hex_to_id("9bed6275068a0575243ba8409253e61af81ab2ff")
@@ -78,7 +75,7 @@ fn whitespace() -> crate::Result {
7875
#[test]
7976
fn unsigned() -> crate::Result {
8077
assert_eq!(
81-
CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::<Result<Vec<_>, _>>()?,
78+
CommitRefIter::from_bytes(&fixture_name("commit", "unsigned.txt")).collect::<Result<Vec<_>, _>>()?,
8279
vec![
8380
Token::Tree {
8481
id: hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d")
@@ -98,7 +95,7 @@ fn unsigned() -> crate::Result {
9895
#[test]
9996
fn signed_singleline() -> crate::Result {
10097
assert_eq!(
101-
CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")).collect::<Result<Vec<_>, _>>()?,
98+
CommitRefIter::from_bytes(&fixture_name("commit", "signed-singleline.txt")).collect::<Result<Vec<_>, _>>()?,
10299
vec![
103100
Token::Tree {
104101
id: hex_to_id("00fc39317701176e326974ce44f5bd545a32ec0b")
@@ -117,7 +114,7 @@ fn signed_singleline() -> crate::Result {
117114
]
118115
);
119116
assert_eq!(
120-
CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt"))
117+
CommitRefIter::from_bytes(&fixture_name("commit", "signed-singleline.txt"))
121118
.parent_ids()
122119
.collect::<Vec<_>>(),
123120
vec![hex_to_id("09d8d3a12e161a7f6afb522dbe8900a9c09bce06")]
@@ -127,7 +124,7 @@ fn signed_singleline() -> crate::Result {
127124

128125
#[test]
129126
fn error_handling() -> crate::Result {
130-
let data = fixture_bytes("commit", "unsigned.txt");
127+
let data = fixture_name("commit", "unsigned.txt");
131128
let iter = CommitRefIter::from_bytes(&data[..data.len() / 2]);
132129
let tokens = iter.collect::<Vec<_>>();
133130
assert!(
@@ -139,7 +136,7 @@ fn error_handling() -> crate::Result {
139136

140137
#[test]
141138
fn mergetag() -> crate::Result {
142-
let input = fixture_bytes("commit", "mergetag.txt");
139+
let input = fixture_name("commit", "mergetag.txt");
143140
let iter = CommitRefIter::from_bytes(&input);
144141
assert_eq!(
145142
iter.collect::<Result<Vec<_>, _>>()?,
@@ -177,14 +174,11 @@ fn mergetag() -> crate::Result {
177174
mod method {
178175
use gix_object::CommitRefIter;
179176

180-
use crate::{
181-
hex_to_id,
182-
immutable::{fixture_bytes, signature},
183-
};
177+
use crate::{fixture_name, hex_to_id, signature};
184178

185179
#[test]
186180
fn tree_id() -> crate::Result {
187-
let input = fixture_bytes("commit", "unsigned.txt");
181+
let input = fixture_name("commit", "unsigned.txt");
188182
let iter = CommitRefIter::from_bytes(&input);
189183
assert_eq!(
190184
iter.clone().tree_id().ok(),
@@ -200,7 +194,7 @@ mod method {
200194

201195
#[test]
202196
fn signatures() -> crate::Result {
203-
let input = fixture_bytes("commit", "unsigned.txt");
197+
let input = fixture_name("commit", "unsigned.txt");
204198
let iter = CommitRefIter::from_bytes(&input);
205199
assert_eq!(
206200
iter.signatures().collect::<Vec<_>>(),

gix-object/tests/immutable/commit/mod.rs renamed to gix-object/tests/commit/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ mod method {
134134
use gix_object::CommitRef;
135135
use pretty_assertions::assert_eq;
136136

137-
use crate::{hex_to_id, immutable::fixture_bytes};
137+
use crate::{fixture_name, hex_to_id};
138138

139139
#[test]
140140
fn tree() -> crate::Result {
141-
let fixture = fixture_bytes("commit", "unsigned.txt");
141+
let fixture = fixture_name("commit", "unsigned.txt");
142142
let commit = CommitRef::from_bytes(&fixture)?;
143143
assert_eq!(commit.tree(), hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d"));
144144
assert_eq!(commit.tree, "1b2dfb4ac5e42080b682fc676e9738c94ce6d54d");

gix-object/tests/encode/mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,26 @@ mod blob {
9595
// It doesn't matter which data we use - it's not interpreted.
9696
round_trip!(gix_object::Blob, gix_object::BlobRef, "tree/everything.tree");
9797
}
98+
99+
mod loose_header {
100+
use bstr::ByteSlice;
101+
use gix_object::{decode, encode, Kind};
102+
103+
#[test]
104+
fn round_trip() -> Result<(), Box<dyn std::error::Error>> {
105+
for (kind, size, expected) in &[
106+
(Kind::Tree, 1234, "tree 1234\0".as_bytes()),
107+
(Kind::Blob, 0, b"blob 0\0"),
108+
(Kind::Commit, 24241, b"commit 24241\0"),
109+
(Kind::Tag, 9999999999, b"tag 9999999999\0"),
110+
] {
111+
let buf = encode::loose_header(*kind, *size);
112+
assert_eq!(buf.as_bstr(), expected.as_bstr());
113+
let (actual_kind, actual_size, actual_read) = decode::loose_header(&buf)?;
114+
assert_eq!(actual_kind, *kind);
115+
assert_eq!(actual_size, *size);
116+
assert_eq!(actual_read, buf.len());
117+
}
118+
Ok(())
119+
}
120+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:9d0ebc472023fffe49d71303e5f41f8c6ca24e28d283468f2426791c6286ecf7
3+
size 10240
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
set -eu -o pipefail
3+
4+
function baseline() {
5+
local revspec=${1:?First argument is the revspec of the object to create a baseline for}
6+
local basename=${2:?Second argument is the name of the baseline file}
7+
local baseline_file="$basename.baseline"
8+
git rev-parse "$revspec" | git cat-file --batch | tail -n +2 > "$baseline_file"
9+
truncate -s "$(($(stat -c '%s' "$baseline_file")-1))" "$baseline_file"
10+
}
11+
12+
git init -q
13+
mkdir file
14+
touch bin bin.d file.to file.toml file.toml.bin file0 file/a
15+
16+
git add .
17+
git commit -m "c1"
18+
19+
baseline @^{tree} tree

0 commit comments

Comments
 (0)