Skip to content

Commit 8385f96

Browse files
committed
tests(record): test no-op record in regression test
There was a bug where if a binary change was not selected, the contents of the file were set to the empty string, rather than their actual previous contents. (This is why the `SelectedContents::Unchanged` variant was created.)
1 parent b59bcf8 commit 8385f96

File tree

1 file changed

+147
-98
lines changed

1 file changed

+147
-98
lines changed

git-branchless-lib/bin/testing/regression_test_record.rs

Lines changed: 147 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,136 @@ use std::path::PathBuf;
66

77
use branchless::core::effects::Effects;
88
use branchless::core::formatting::Glyphs;
9-
use branchless::git::{hydrate_tree, process_diff_for_record, FileMode, MaybeZeroOid, Repo};
9+
use branchless::git::{
10+
hydrate_tree, process_diff_for_record, Commit, FileMode, MaybeZeroOid, NonZeroOid, Repo, Tree,
11+
};
1012
use bstr::ByteSlice;
1113
use eyre::Context;
1214
use scm_record::{File, Section, SelectedContents};
1315

16+
fn entries_from_files(
17+
repo: &Repo,
18+
old_tree: &Tree,
19+
new_tree: &Tree,
20+
files: &[File],
21+
) -> eyre::Result<HashMap<PathBuf, Option<(NonZeroOid, FileMode)>>> {
22+
let entries = files
23+
.into_iter()
24+
.map(|file| {
25+
let file_path = file.path.clone().into_owned();
26+
let value = {
27+
let (selected, _unselected) = file.get_selected_contents();
28+
let blob_oid = match selected {
29+
SelectedContents::Absent => return Ok((file_path, None)),
30+
SelectedContents::Unchanged => {
31+
old_tree.get_oid_for_path(&file.path)?.unwrap_or_default()
32+
}
33+
SelectedContents::Binary {
34+
old_description: _,
35+
new_description: _,
36+
} => new_tree.get_oid_for_path(&file.path)?.unwrap(),
37+
SelectedContents::Present { contents } => {
38+
MaybeZeroOid::NonZero(repo.create_blob_from_contents(contents.as_bytes())?)
39+
}
40+
};
41+
match blob_oid {
42+
MaybeZeroOid::Zero => None,
43+
MaybeZeroOid::NonZero(blob_oid) => {
44+
let new_file_mode = file
45+
.get_file_mode()
46+
.expect("File mode should have been set");
47+
let file_mode = i32::try_from(new_file_mode).unwrap();
48+
let file_mode = FileMode::from(file_mode);
49+
Some((blob_oid, file_mode))
50+
}
51+
}
52+
};
53+
Ok((file_path, value))
54+
})
55+
.collect::<eyre::Result<_>>()?;
56+
Ok(entries)
57+
}
58+
59+
fn select_all(mut entries: Vec<File>) -> Vec<File> {
60+
for File {
61+
path: _,
62+
file_mode: _,
63+
sections,
64+
} in &mut entries
65+
{
66+
for section in sections {
67+
match section {
68+
Section::Unchanged { lines: _ } => {}
69+
Section::Changed { lines } => {
70+
for line in lines {
71+
line.is_toggled = true;
72+
}
73+
}
74+
Section::FileMode {
75+
is_toggled,
76+
before: _,
77+
after: _,
78+
}
79+
| Section::Binary {
80+
is_toggled,
81+
old_description: _,
82+
new_description: _,
83+
} => {
84+
*is_toggled = true;
85+
}
86+
}
87+
}
88+
}
89+
entries
90+
}
91+
92+
fn assert_trees_equal(
93+
test: &str,
94+
repo: &Repo,
95+
parent_commit: &Commit,
96+
current_commit: &Commit,
97+
expected_tree: &Tree,
98+
entries: &[File],
99+
) -> eyre::Result<()> {
100+
let old_tree = parent_commit.get_tree()?;
101+
let new_tree = current_commit.get_tree()?;
102+
let entries = entries_from_files(repo, &old_tree, &new_tree, entries)?;
103+
let actual_tree_oid = hydrate_tree(&repo, Some(&old_tree), entries)?;
104+
let actual_tree = repo.find_tree_or_fail(actual_tree_oid)?;
105+
let actual_commit = {
106+
let author = current_commit.get_author();
107+
let committer = current_commit.get_committer();
108+
let message = current_commit.get_message_raw();
109+
let message = message.to_str_lossy();
110+
let parents = current_commit.get_parents();
111+
let actual_oid = repo.create_commit(
112+
None,
113+
&author,
114+
&committer,
115+
&message,
116+
&actual_tree,
117+
parents.iter().collect(),
118+
)?;
119+
repo.find_commit_or_fail(actual_oid)?
120+
};
121+
if actual_tree.get_oid() != expected_tree.get_oid() {
122+
eyre::bail!(
123+
"\
124+
Trees are NOT equal for test {test:?}
125+
Actual: {actual} vs expected: {expected}
126+
Try running:
127+
git diff-tree -p {expected} {actual}
128+
Or examine the new (wrong) commit with:
129+
git show {commit_oid}",
130+
expected = expected_tree.get_oid().to_string(),
131+
actual = actual_tree.get_oid().to_string(),
132+
commit_oid = actual_commit.get_oid(),
133+
);
134+
}
135+
136+
Ok(())
137+
}
138+
14139
fn main() -> eyre::Result<()> {
15140
let path_to_repo = std::env::var("PATH_TO_REPO")
16141
.wrap_err("Could not read PATH_TO_REPO environment variable")?;
@@ -34,105 +159,29 @@ fn main() -> eyre::Result<()> {
34159
let new_tree = current_commit.get_tree()?;
35160
let diff = repo.get_diff_between_trees(&effects, Some(&old_tree), &new_tree, 0)?;
36161

37-
let entries = {
38-
let mut entries = process_diff_for_record(&repo, &diff)?;
39-
for File {
40-
path: _,
41-
file_mode: _,
42-
sections,
43-
} in &mut entries
44-
{
45-
for section in sections {
46-
match section {
47-
Section::Unchanged { lines: _ } => {}
48-
Section::Changed { lines } => {
49-
for line in lines {
50-
line.is_toggled = true;
51-
}
52-
}
53-
Section::FileMode {
54-
is_toggled,
55-
before: _,
56-
after: _,
57-
}
58-
| Section::Binary {
59-
is_toggled,
60-
old_description: _,
61-
new_description: _,
62-
} => {
63-
*is_toggled = true;
64-
}
65-
}
66-
}
67-
}
68-
entries
69-
};
70-
let entries: HashMap<_, _> = entries
71-
.into_iter()
72-
.map(|file| {
73-
let file_path = file.path.clone().into_owned();
74-
let value = {
75-
let (selected, _unselected) = file.get_selected_contents();
76-
let blob_oid = match selected {
77-
SelectedContents::Absent => return Ok((file_path, None)),
78-
SelectedContents::Unchanged => {
79-
old_tree.get_oid_for_path(&file.path)?.unwrap_or_default()
80-
}
81-
SelectedContents::Binary {
82-
old_description: _,
83-
new_description: _,
84-
} => new_tree.get_oid_for_path(&file.path)?.unwrap(),
85-
SelectedContents::Present { contents } => MaybeZeroOid::NonZero(
86-
repo.create_blob_from_contents(contents.as_bytes())?,
87-
),
88-
};
89-
match blob_oid {
90-
MaybeZeroOid::Zero => None,
91-
MaybeZeroOid::NonZero(blob_oid) => {
92-
let new_file_mode = file
93-
.get_file_mode()
94-
.expect("File mode should have been set");
95-
let file_mode = i32::try_from(new_file_mode).unwrap();
96-
let file_mode = FileMode::from(file_mode);
97-
Some((blob_oid, file_mode))
98-
}
99-
}
100-
};
101-
Ok((file_path, value))
102-
})
103-
.collect::<eyre::Result<_>>()?;
162+
let entries = process_diff_for_record(&repo, &diff)?;
163+
{
164+
assert_trees_equal(
165+
&format!("select-none {parent_commit:?}"),
166+
&repo,
167+
&parent_commit,
168+
&current_commit,
169+
&parent_commit.get_tree()?,
170+
&entries,
171+
)?;
172+
}
104173

105-
let actual_tree_oid = hydrate_tree(&repo, Some(&old_tree), entries)?;
106-
let actual_tree = repo.find_tree_or_fail(actual_tree_oid)?;
107-
let actual_commit = {
108-
let author = current_commit.get_author();
109-
let committer = current_commit.get_committer();
110-
let message = current_commit.get_message_raw();
111-
let message = message.to_str_lossy();
112-
let parents = current_commit.get_parents();
113-
let actual_oid = repo.create_commit(
114-
None,
115-
&author,
116-
&committer,
117-
&message,
118-
&actual_tree,
119-
parents.iter().collect(),
174+
// Select all changes (the resulting tree should be identical).
175+
{
176+
let entries = select_all(entries);
177+
assert_trees_equal(
178+
&format!("select-all {current_commit:?}"),
179+
&repo,
180+
&parent_commit,
181+
&current_commit,
182+
&current_commit.get_tree()?,
183+
&entries,
120184
)?;
121-
repo.find_commit_or_fail(actual_oid)?
122-
};
123-
let expected_tree = current_commit.get_tree()?;
124-
if actual_tree.get_oid() != expected_tree.get_oid() {
125-
println!(
126-
"Trees are NOT equal, actual {actual} vs expected {expected}\n\
127-
Try running:\n\
128-
git diff-tree -p {expected} {actual}\n\
129-
Or examine the new (wrong) commit with:\n\
130-
git show {commit_oid}",
131-
expected = expected_tree.get_oid().to_string(),
132-
actual = actual_tree.get_oid().to_string(),
133-
commit_oid = actual_commit.get_oid(),
134-
);
135-
std::process::exit(1);
136185
}
137186
}
138187

0 commit comments

Comments
 (0)