Skip to content

Commit 460ddb3

Browse files
Add overwriting of author to squash filter
Change: squash-author
1 parent 454f1c3 commit 460ddb3

File tree

4 files changed

+75
-32
lines changed

4 files changed

+75
-32
lines changed

src/bin/josh-filter.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ fn make_app() -> clap::Command<'static> {
4545
.long("squash")
4646
.takes_value(true),
4747
)
48+
.arg(
49+
clap::Arg::new("author")
50+
.help("Author to use for commits with rewritten message")
51+
.long("author")
52+
.takes_value(true),
53+
)
54+
.arg(
55+
clap::Arg::new("email")
56+
.help("Author email to use for commits with rewritten message")
57+
.long("email")
58+
.takes_value(true),
59+
)
4860
.arg(
4961
clap::Arg::new("single")
5062
.help("Produce a history that contains only one single commit")
@@ -200,7 +212,14 @@ fn run_filter(args: Vec<String>) -> josh::JoshResult<i32> {
200212
refs.push((reference.name().unwrap().to_string(), target));
201213
}
202214
}
203-
filterobj = josh::filter::chain(josh::filter::squash(Some(&ids)), filterobj);
215+
filterobj = josh::filter::chain(
216+
josh::filter::squash(Some((
217+
args.value_of("author").unwrap(),
218+
args.value_of("email").unwrap(),
219+
&ids,
220+
))),
221+
filterobj,
222+
);
204223
};
205224

206225
let odb = repo.odb()?;

src/filter/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,12 @@ pub fn empty() -> Filter {
6161
to_filter(Op::Empty)
6262
}
6363

64-
pub fn squash(ids: Option<&[(git2::Oid, String)]>) -> Filter {
65-
if let Some(ids) = ids {
64+
pub fn squash(ids: Option<(&str, &str, &[(git2::Oid, String)])>) -> Filter {
65+
if let Some((author, email, ids)) = ids {
6666
to_filter(Op::Squash(Some(
67-
ids.iter().map(|(x, y)| (*x, y.clone())).collect(),
67+
ids.iter()
68+
.map(|(x, y)| (*x, (y.clone(), author.to_string(), email.to_string())))
69+
.collect(),
6870
)))
6971
} else {
7072
to_filter(Op::Squash(None))
@@ -95,7 +97,7 @@ enum Op {
9597
Empty,
9698
Fold,
9799
Paths,
98-
Squash(Option<std::collections::HashMap<git2::Oid, String>>),
100+
Squash(Option<std::collections::HashMap<git2::Oid, (String, String, String)>>),
99101
Linear,
100102

101103
RegexReplace(regex::Regex, String),
@@ -250,7 +252,7 @@ fn spec2(op: &Op) -> String {
250252
Op::Squash(Some(hs)) => {
251253
let mut v = hs
252254
.iter()
253-
.map(|(x, y)| format!("{}:{}", x, y))
255+
.map(|(x, y)| format!("{}:{}:{}:{}", x, y.0, y.1, y.2))
254256
.collect::<Vec<String>>();
255257
v.sort();
256258
let s = v.join(",");

src/history.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,21 +181,29 @@ pub fn rewrite_commit(
181181
base: &git2::Commit,
182182
parents: &[&git2::Commit],
183183
tree: &git2::Tree,
184-
message: Option<String>,
184+
message: Option<(String, String, String)>,
185185
) -> JoshResult<git2::Oid> {
186186
if message == None && base.tree()?.id() == tree.id() && all_equal(base.parents(), parents) {
187187
// Looks like an optimization, but in fact serves to not change the commit in case
188188
// it was signed.
189189
return Ok(base.id());
190190
}
191191

192-
let b = repo.commit_create_buffer(
193-
&base.author(),
194-
&base.committer(),
195-
&message.unwrap_or(base.message_raw().unwrap_or("no message").to_string()),
196-
tree,
197-
parents,
198-
)?;
192+
let b = if let Some((message, author, email)) = message {
193+
let a = base.author();
194+
let new_a = git2::Signature::new(&author, &email, &a.when())?;
195+
let c = base.committer();
196+
let new_c = git2::Signature::new(&author, &email, &c.when())?;
197+
repo.commit_create_buffer(&new_a, &new_c, &message, tree, parents)?
198+
} else {
199+
repo.commit_create_buffer(
200+
&base.author(),
201+
&base.committer(),
202+
&base.message_raw().unwrap_or("no message"),
203+
tree,
204+
parents,
205+
)?
206+
};
199207

200208
if let Ok((sig, _)) = repo.extract_signature(&base.id(), None) {
201209
// Re-create the object with the original signature (which of course does not match any
@@ -551,7 +559,7 @@ pub fn create_filtered_commit<'a>(
551559
filtered_tree: git2::Tree<'a>,
552560
transaction: &cache::Transaction,
553561
filter: filter::Filter,
554-
message: Option<String>,
562+
message: Option<(String, String, String)>,
555563
) -> JoshResult<git2::Oid> {
556564
let (r, is_new) = create_filtered_commit2(
557565
transaction.repo(),
@@ -573,7 +581,7 @@ fn create_filtered_commit2<'a>(
573581
original_commit: &'a git2::Commit,
574582
filtered_parent_ids: Vec<git2::Oid>,
575583
filtered_tree: git2::Tree<'a>,
576-
message: Option<String>,
584+
message: Option<(String, String, String)>,
577585
) -> JoshResult<(git2::Oid, bool)> {
578586
let filtered_parent_commits: Result<Vec<_>, _> = filtered_parent_ids
579587
.iter()

tests/filter/squash.t

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
$ git merge -q branch2 --no-ff
3030

31-
$ josh-filter -s --squash "refs/tags/*" --update refs/heads/filtered
31+
$ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered
3232
Warning: reference refs/heads/filtered wasn't updated
3333
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
3434

@@ -38,14 +38,15 @@
3838
'git <command> [<revision>...] -- [<file>...]'
3939
[128]
4040
$ git tag tag_a 1d69b7d
41-
$ josh-filter -s --squash "refs/tags/*" --update refs/heads/filtered
41+
$ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered
4242
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
43-
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
43+
[2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96
4444

4545
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
46-
* 97a9ff7bd4dad25b9dacdfdaeb861e74e7b4aef8 (tag: filtered/tag_a, filtered) refs/tags/tag_a
46+
* d8aa5a9937f4f0bd645dbc0b591bae5cd6b6d91b (tag: filtered/tag_a, filtered) refs/tags/tag_a
4747
$ git tag tag_b 0b4cf6c
4848

49+
4950
$ git log --graph --decorate --pretty=oneline
5051
* 1d69b7d2651f744be3416f2ad526aeccefb99310 (HEAD -> master, tag: tag_a) Merge branch 'branch2'
5152
|\
@@ -55,28 +56,41 @@
5556
|/
5657
* 0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb (tag: tag_b) add file1
5758

58-
$ josh-filter -s --squash "refs/tags/*" --update refs/heads/filtered
59+
$ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered
5960
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
60-
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
61-
[3] :SQUASH=1683a7fc84387b56a1a5de8e9fcf720166951949
61+
[2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96
62+
[3] :SQUASH=3953063f3dc58661e9db16f9014aab1e8ec50bf8
6263

6364
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
64-
* fa3bd3f0d90d5894c6ac402ef5f764b75335ec01 (tag: filtered/tag_a, filtered) refs/tags/tag_a
65+
* 5b1a753860ca124024f6dfb4fd018fe7df8beae4 (tag: filtered/tag_a, filtered) refs/tags/tag_a
66+
|\
67+
* 96a731a4d64a8928e6af7abb2d425df3812b4197 (tag: filtered/tag_b) refs/tags/tag_b
68+
69+
$ git log --graph --pretty=%an:%ae refs/heads/master
70+
* Josh:josh@example.com
71+
|\
72+
| * Josh:josh@example.com
73+
| * Josh:josh@example.com
74+
* | Josh:josh@example.com
75+
|/
76+
* Josh:josh@example.com
77+
$ git log --graph --pretty=%an:%ae refs/heads/filtered
78+
* New Author:new@e.mail
6579
|\
66-
* 077b2cad7b3fbc393b6320b90c9c0be1255ac309 (tag: filtered/tag_b) refs/tags/tag_b
80+
* New Author:new@e.mail
6781

6882
$ git tag tag_c 975d4c4
6983

70-
$ josh-filter -s --squash "refs/tags/*" --update refs/heads/filtered
84+
$ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered
7185
[1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
72-
[2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e
73-
[3] :SQUASH=1683a7fc84387b56a1a5de8e9fcf720166951949
74-
[6] :SQUASH=06a82cb9d2d3abb0ac59f8c782fd7edecc8e8d28
86+
[2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96
87+
[3] :SQUASH=3953063f3dc58661e9db16f9014aab1e8ec50bf8
88+
[6] :SQUASH=6a132477d438779dbaeb0d68b9aab55786e28dd9
7589

7690
$ git log --graph --decorate --pretty=oneline refs/heads/filtered
77-
* dc1dc0211db7a1aea1234af950b4946afa5a6f14 (tag: filtered/tag_a, filtered) refs/tags/tag_a
91+
* 9fe45cb2bead844630852ab338ecd8e073f8ba50 (tag: filtered/tag_a, filtered) refs/tags/tag_a
7892
|\
79-
| * 500760f4e4f3d4ba6e73af7ce0a98d91a25a503a (tag: filtered/tag_c) refs/tags/tag_c
93+
| * d6b88d4c1cc566b7f4d9b51353ec6f3204a93b81 (tag: filtered/tag_c) refs/tags/tag_c
8094
|/
81-
* 077b2cad7b3fbc393b6320b90c9c0be1255ac309 (tag: filtered/tag_b) refs/tags/tag_b
95+
* 96a731a4d64a8928e6af7abb2d425df3812b4197 (tag: filtered/tag_b) refs/tags/tag_b
8296

0 commit comments

Comments
 (0)