Skip to content

Commit 2c46476

Browse files
temp(split): try out new commit message format
See arxanas#1462
1 parent 55d4536 commit 2c46476

File tree

4 files changed

+100
-31
lines changed

4 files changed

+100
-31
lines changed

git-branchless-lib/src/git/diff.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashMap;
33
use std::path::PathBuf;
44
use std::sync::{Arc, Mutex};
55

6-
use eyre::Context;
6+
use eyre::{Context, OptionExt};
77
use itertools::Itertools;
88
use scm_record::helpers::make_binary_description;
99
use scm_record::{ChangeType, File, FileMode, Section, SectionChangedLine};
@@ -15,6 +15,17 @@ pub struct Diff<'repo> {
1515
pub(super) inner: git2::Diff<'repo>,
1616
}
1717

18+
impl Diff<'_> {
19+
/// Summarize this diff into a single line "short" format.
20+
pub fn short_stats(&self) -> eyre::Result<String> {
21+
let stats = self.inner.stats()?;
22+
let buf = stats.to_buf(git2::DiffStatsFormat::SHORT, usize::MAX)?;
23+
buf.as_str()
24+
.ok_or_eyre("converting buf to str")
25+
.map(|s| s.trim().to_string())
26+
}
27+
}
28+
1829
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1930
struct GitHunk {
2031
old_start: usize,
@@ -23,6 +34,59 @@ struct GitHunk {
2334
new_lines: usize,
2435
}
2536

37+
/// Summarize a diff for use as part of a temporary commit message.
38+
pub fn summarize_diff_for_temporary_commit(diff: &Diff) -> eyre::Result<String> {
39+
// this returns something like `1 file changed, 1 deletion(-)`
40+
// diff.short_stats()
41+
42+
// this returns something like `test2.txt (-1)` or `2 files (+1/-2)`
43+
let stats = diff.inner.stats()?;
44+
let prefix = if stats.files_changed() == 1 {
45+
let mut prefix = None;
46+
// returning false terminates iteration, but that also returns Err, so
47+
// catch and ignore it
48+
let _ = diff.inner.foreach(
49+
&mut |delta: git2::DiffDelta, _| {
50+
if let Some(path) = delta.old_file().path() {
51+
// prefix = Some(format!("{}", path.file_name().unwrap().to_string_lossy()));
52+
prefix = Some(format!("{}", path.display()));
53+
} else if let Some(path) = delta.new_file().path() {
54+
prefix = Some(format!("{}", path.display()));
55+
}
56+
57+
false
58+
},
59+
None,
60+
None,
61+
None,
62+
);
63+
prefix
64+
} else {
65+
Some(format!("{} files", stats.files_changed()))
66+
};
67+
68+
let i = stats.insertions();
69+
let d = stats.deletions();
70+
Ok(format!(
71+
"{prefix} ({i}{slash}{d})",
72+
prefix = prefix.unwrap(),
73+
i = if i > 0 {
74+
format!("+{i}")
75+
} else {
76+
String::new()
77+
},
78+
slash = if i > 0 && d > 0 { "/" } else { "" },
79+
d = if d > 0 {
80+
format!("-{d}")
81+
} else {
82+
String::new()
83+
}
84+
))
85+
// stats.files_changed()
86+
// stats.insertions()
87+
// stats.deletions()
88+
}
89+
2690
/// Calculate the diff between the index and the working copy.
2791
pub fn process_diff_for_record(repo: &Repo, diff: &Diff) -> eyre::Result<Vec<File<'static>>> {
2892
let Diff { inner: diff } = diff;

git-branchless-lib/src/git/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod test;
1414
mod tree;
1515

1616
pub use config::{Config, ConfigRead, ConfigValue, ConfigWrite};
17-
pub use diff::{process_diff_for_record, Diff};
17+
pub use diff::{process_diff_for_record, summarize_diff_for_temporary_commit, Diff};
1818
pub use index::{update_index, Index, IndexEntry, Stage, UpdateIndexCommand};
1919
pub use object::Commit;
2020
pub use oid::{MaybeZeroOid, NonZeroOid};

git-branchless/src/commands/split.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use lib::{
2626
},
2727
},
2828
git::{
29-
make_empty_tree, CherryPickFastOptions, GitRunInfo, MaybeZeroOid, NonZeroOid, Repo,
30-
ResolvedReferenceInfo,
29+
make_empty_tree, summarize_diff_for_temporary_commit, CherryPickFastOptions, GitRunInfo,
30+
MaybeZeroOid, NonZeroOid, Repo, ResolvedReferenceInfo,
3131
},
3232
try_exit_code,
3333
util::{ExitCode, EyreExitOr},
@@ -135,12 +135,6 @@ pub fn split(
135135
}
136136
};
137137

138-
let mut message = match files_to_extract.as_slice() {
139-
[] => unreachable!("Clap should have required at least 1 file"),
140-
[_] => None,
141-
other => Some(format!("{} files", other.len())),
142-
};
143-
144138
for file in files_to_extract.iter() {
145139
let path = Path::new(&file).to_path_buf();
146140
let cwd = std::env::current_dir()?;
@@ -176,7 +170,6 @@ pub fn split(
176170
path
177171
};
178172
let path = path.as_path();
179-
message = message.or(Some(path.to_string_lossy().to_string()));
180173

181174
if let Ok(Some(false)) = target_commit.contains_touched_path(path) {
182175
writeln!(
@@ -227,7 +220,19 @@ pub fn split(
227220
.find_tree(temp_tree_oid)?
228221
.expect("should have been found");
229222
}
230-
let message = message.expect("at least 1 file should have been given");
223+
let message = {
224+
let (effects, _progress) =
225+
effects.start_operation(lib::core::effects::OperationType::CalculateDiff);
226+
let (old_tree, new_tree) = (&remainder_tree, &target_tree);
227+
let diff = repo.get_diff_between_trees(
228+
&effects,
229+
Some(old_tree),
230+
new_tree,
231+
0, // we don't care about the context here
232+
)?;
233+
234+
summarize_diff_for_temporary_commit(&diff)?
235+
};
231236

232237
let remainder_commit_oid =
233238
target_commit.amend_commit(None, None, None, None, Some(&remainder_tree))?;

git-branchless/tests/test_split.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn test_split_detached_head() -> eyre::Result<()> {
3232
|
3333
@ 2932db7 first commit
3434
|
35-
o c159d6a temp(split): test2.txt
35+
o 01523cc temp(split): test2.txt (+1)
3636
"###);
3737
}
3838

@@ -91,7 +91,7 @@ fn test_split_added_file() -> eyre::Result<()> {
9191
|
9292
@ 2f9e232 first commit
9393
|
94-
o 067feb9 temp(split): test2.txt
94+
o c4b067e temp(split): test2.txt (+1)
9595
"###);
9696
}
9797

@@ -148,7 +148,7 @@ fn test_split_modified_file() -> eyre::Result<()> {
148148
|
149149
@ 495b4c0 first commit
150150
|
151-
o 590b05e temp(split): test1.txt
151+
o 5375cb6 temp(split): test1.txt (+1/-1)
152152
"###);
153153
}
154154

@@ -215,7 +215,7 @@ fn test_split_deleted_file() -> eyre::Result<()> {
215215
|
216216
@ 495b4c0 first commit
217217
|
218-
o bfc063a temp(split): test1.txt
218+
o de6e4df temp(split): test1.txt (-1)
219219
"###);
220220
}
221221

@@ -268,7 +268,7 @@ fn test_split_multiple_files() -> eyre::Result<()> {
268268
|
269269
@ 8e5c74b first commit
270270
|
271-
o 0b1f3c6 temp(split): 2 files
271+
o 57020b0 temp(split): 2 files (+2)
272272
"###);
273273
}
274274

@@ -324,7 +324,7 @@ fn test_split_detached_branch() -> eyre::Result<()> {
324324
|
325325
@ 2932db7 (branch-name) first commit
326326
|
327-
o c159d6a temp(split): test2.txt
327+
o 01523cc temp(split): test2.txt (+1)
328328
"###);
329329
}
330330

@@ -368,7 +368,7 @@ fn test_split_attached_branch() -> eyre::Result<()> {
368368
|
369369
o 2932db7 first commit
370370
|
371-
@ c159d6a (> branch-name) temp(split): test2.txt
371+
@ 01523cc (> branch-name) temp(split): test2.txt (+1)
372372
"###);
373373

374374
let (stdout, _stderr) = git.run(&["status", "--short"])?;
@@ -407,17 +407,17 @@ fn test_split_restacks_descendents() -> eyre::Result<()> {
407407
let (stdout, _stderr) = git.branchless("split", &["HEAD~", "test2.txt"])?;
408408
insta::assert_snapshot!(&stdout, @r###"
409409
Attempting rebase in-memory...
410-
[1/1] Committed as: 71d03a3 create test3.txt
410+
[1/1] Committed as: a629a22 create test3.txt
411411
branchless: processing 1 rewritten commit
412-
branchless: running command: <git-executable> checkout 71d03a33c534eda4253fc8772a4c0d5e9515127c
412+
branchless: running command: <git-executable> checkout a629a22974b9232523701e66e6e2bcdf8ffc8ad1
413413
In-memory rebase succeeded.
414414
O f777ecc (master) create initial.txt
415415
|
416416
o 2932db7 first commit
417417
|
418-
o c159d6a temp(split): test2.txt
418+
o 01523cc temp(split): test2.txt (+1)
419419
|
420-
@ 71d03a3 create test3.txt
420+
@ a629a22 create test3.txt
421421
"###);
422422
}
423423

@@ -468,17 +468,17 @@ fn test_split_undo_works() -> eyre::Result<()> {
468468
let (stdout, _stderr) = git.branchless("split", &["HEAD~", "test2.txt"])?;
469469
insta::assert_snapshot!(&stdout, @r###"
470470
Attempting rebase in-memory...
471-
[1/1] Committed as: 71d03a3 create test3.txt
471+
[1/1] Committed as: a629a22 create test3.txt
472472
branchless: processing 1 rewritten commit
473-
branchless: running command: <git-executable> checkout 71d03a33c534eda4253fc8772a4c0d5e9515127c
473+
branchless: running command: <git-executable> checkout a629a22974b9232523701e66e6e2bcdf8ffc8ad1
474474
In-memory rebase succeeded.
475475
O f777ecc (master) create initial.txt
476476
|
477477
o 2932db7 first commit
478478
|
479-
o c159d6a temp(split): test2.txt
479+
o 01523cc temp(split): test2.txt (+1)
480480
|
481-
@ 71d03a3 create test3.txt
481+
@ a629a22 create test3.txt
482482
"###);
483483
}
484484

@@ -561,7 +561,7 @@ fn test_split_supports_absolute_relative_and_repo_relative_paths() -> eyre::Resu
561561
|
562562
@ d9d41a3 first commit
563563
|
564-
o fc76a91 temp(split): subdir/test3.txt
564+
o 98da165 temp(split): subdir/test3.txt (+1)
565565
"###);
566566

567567
let (stdout, _stderr) = git.run(&["show", "--pretty=format:", "--stat", "HEAD"])?;
@@ -593,7 +593,7 @@ fn test_split_supports_absolute_relative_and_repo_relative_paths() -> eyre::Resu
593593
|
594594
@ 0cb8154 first commit
595595
|
596-
o 5d2c1d0 temp(split): subdir/test1.txt
596+
o 89564a0 temp(split): subdir/test1.txt (+1)
597597
"###);
598598

599599
let (stdout, _stderr) = git.run(&["show", "--pretty=format:", "--stat", "HEAD"])?;
@@ -625,7 +625,7 @@ fn test_split_supports_absolute_relative_and_repo_relative_paths() -> eyre::Resu
625625
|
626626
@ 9122046 first commit
627627
|
628-
o ba3abaf temp(split): test2.txt
628+
o c3d37e6 temp(split): test2.txt (+1)
629629
"###);
630630

631631
let (stdout, _stderr) = git.run(&["show", "--pretty=format:", "--stat", "HEAD"])?;
@@ -657,7 +657,7 @@ fn test_split_supports_absolute_relative_and_repo_relative_paths() -> eyre::Resu
657657
|
658658
@ 6d0cd9b first commit
659659
|
660-
o 2f03a38 temp(split): test1.txt
660+
o 9eeb11b temp(split): test1.txt (+1)
661661
"###);
662662

663663
let (stdout, _stderr) = git.run(&["show", "--pretty=format:", "--stat", "HEAD"])?;

0 commit comments

Comments
 (0)