From 76b9f3ae7c513c29c8f465b28726cfee442bc2c1 Mon Sep 17 00:00:00 2001 From: Christian Schilling Date: Thu, 5 Jan 2023 12:34:10 +0100 Subject: [PATCH] Split author overwriting into it's own filter Change: author-filter --- josh-proxy/src/lib.rs | 1 + src/bin/josh-filter.rs | 9 +-------- src/filter/mod.rs | 27 +++++++++++++++++++-------- src/filter/parse.rs | 1 + src/history.rs | 28 +++++++++++++++------------- tests/filter/squash.t | 21 ++++++++++++--------- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/josh-proxy/src/lib.rs b/josh-proxy/src/lib.rs index af3fb217e..8d6567398 100644 --- a/josh-proxy/src/lib.rs +++ b/josh-proxy/src/lib.rs @@ -403,6 +403,7 @@ fn split_changes( &vec![&parent], &new_tree, None, + None, false, )?; changes[i].1 = new_commit; diff --git a/src/bin/josh-filter.rs b/src/bin/josh-filter.rs index 14b3778aa..6ac598e34 100644 --- a/src/bin/josh-filter.rs +++ b/src/bin/josh-filter.rs @@ -194,14 +194,7 @@ fn run_filter(args: Vec) -> josh::JoshResult { refs.push((reference.name().unwrap().to_string(), target)); } } - filterobj = josh::filter::chain( - josh::filter::squash(Some(( - args.get_one::("author").unwrap(), - args.get_one::("email").unwrap(), - &ids, - ))), - filterobj, - ); + filterobj = josh::filter::chain(josh::filter::squash(Some(&ids)), filterobj); }; let odb = repo.odb()?; diff --git a/src/filter/mod.rs b/src/filter/mod.rs index dadf5ac09..3c19275fa 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -61,12 +61,10 @@ pub fn empty() -> Filter { to_filter(Op::Empty) } -pub fn squash(ids: Option<(&str, &str, &[(git2::Oid, String)])>) -> Filter { - if let Some((author, email, ids)) = ids { +pub fn squash(ids: Option<&[(git2::Oid, String)]>) -> Filter { + if let Some(ids) = ids { to_filter(Op::Squash(Some( - ids.iter() - .map(|(x, y)| (*x, (y.clone(), author.to_string(), email.to_string()))) - .collect(), + ids.iter().map(|(x, y)| (*x, y.clone())).collect(), ))) } else { to_filter(Op::Squash(None)) @@ -97,7 +95,8 @@ enum Op { Empty, Fold, Paths, - Squash(Option>), + Squash(Option>), + Author(String, String), Rev(std::collections::HashMap), Linear, Unsign, @@ -283,7 +282,7 @@ fn spec2(op: &Op) -> String { Op::Squash(Some(hs)) => { let mut v = hs .iter() - .map(|(x, y)| format!("{}:{}:{}:{}", x, y.0, y.1, y.2)) + .map(|(x, y)| format!("{}:{}", x, y)) .collect::>(); v.sort(); let s = v.join(","); @@ -297,6 +296,9 @@ fn spec2(op: &Op) -> String { Op::File(path) => format!("::{}", parse::quote_if(&path.to_string_lossy())), Op::Prefix(path) => format!(":prefix={}", parse::quote_if(&path.to_string_lossy())), Op::Glob(pattern) => format!("::{}", parse::quote_if(pattern)), + Op::Author(author, email) => { + format!(":author={};{}", parse::quote(author), parse::quote(email)) + } } } @@ -403,6 +405,7 @@ fn apply_to_commit2( &[], &commit.tree()?, None, + None, true, )) .transpose() @@ -481,6 +484,7 @@ fn apply_to_commit2( transaction, filter, None, + None, )) .transpose(); } @@ -502,7 +506,6 @@ fn apply_to_commit2( commit.tree()?, transaction, filter, - None, )) .transpose(); } @@ -586,6 +589,7 @@ fn apply_to_commit2( transaction, filter, None, + None, )) .transpose(); } @@ -662,6 +666,11 @@ fn apply_to_commit2( let filtered_parent_ids = some_or!(filtered_parent_ids, { return Ok(None) }); + let author = match to_op(filter) { + Op::Author(author, email) => Some((author.clone(), email.clone())), + _ => None, + }; + let message = match to_op(filter) { Op::Squash(Some(ids)) => ids.get(&commit.id()).map(|x| x.clone()), _ => None, @@ -673,6 +682,7 @@ fn apply_to_commit2( filtered_tree, transaction, filter, + author, message, )) .transpose() @@ -698,6 +708,7 @@ fn apply2<'a>( Op::Empty => return Ok(tree::empty(repo)), Op::Fold => Ok(tree), Op::Squash(None) => Ok(tree), + Op::Author(_, _) => Ok(tree), Op::Squash(Some(_)) => Err(josh_error("not applicable to tree")), Op::Linear => Ok(tree), Op::Unsign => Ok(tree), diff --git a/src/filter/parse.rs b/src/filter/parse.rs index ab91946ae..e4f0a09dc 100644 --- a/src/filter/parse.rs +++ b/src/filter/parse.rs @@ -7,6 +7,7 @@ fn make_op(args: &[&str]) -> JoshResult { ["nop"] => Ok(Op::Nop), ["empty"] => Ok(Op::Empty), ["prefix", arg] => Ok(Op::Prefix(Path::new(arg).to_owned())), + ["author", author, email] => Ok(Op::Author(author.to_string(), email.to_string())), ["workspace", arg] => Ok(Op::Workspace(Path::new(arg).to_owned())), ["prefix"] => Err(josh_error(indoc!( r#" diff --git a/src/history.rs b/src/history.rs index 164e201fb..47a499817 100644 --- a/src/history.rs +++ b/src/history.rs @@ -181,23 +181,20 @@ pub fn rewrite_commit( base: &git2::Commit, parents: &[&git2::Commit], tree: &git2::Tree, - message: Option<(String, String, String)>, + author: Option<(String, String)>, + message: Option, unsign: bool, ) -> JoshResult { - let b = if let Some((message, author, email)) = message { + let message = message.unwrap_or(base.message_raw().unwrap_or("no message").to_string()); + + let b = if let Some((author, email)) = author { let a = base.author(); let new_a = git2::Signature::new(&author, &email, &a.when())?; let c = base.committer(); let new_c = git2::Signature::new(&author, &email, &c.when())?; repo.commit_create_buffer(&new_a, &new_c, &message, tree, parents)? } else { - repo.commit_create_buffer( - &base.author(), - &base.committer(), - &base.message_raw().unwrap_or("no message"), - tree, - parents, - )? + repo.commit_create_buffer(&base.author(), &base.committer(), &message, tree, parents)? }; if let (false, Ok((sig, _))) = (unsign, repo.extract_signature(&base.id(), None)) { @@ -508,6 +505,7 @@ pub fn unapply_filter( &original_parents_refs, &new_tree, None, + None, false, )?; @@ -556,14 +554,14 @@ pub fn remove_commit_signature<'a>( filtered_tree: git2::Tree<'a>, transaction: &cache::Transaction, filter: filter::Filter, - message: Option<(String, String, String)>, ) -> JoshResult { let (r, is_new) = create_filtered_commit2( transaction.repo(), original_commit, filtered_parent_ids, filtered_tree, - message, + None, + None, true, )?; @@ -597,13 +595,15 @@ pub fn create_filtered_commit<'a>( filtered_tree: git2::Tree<'a>, transaction: &cache::Transaction, filter: filter::Filter, - message: Option<(String, String, String)>, + author: Option<(String, String)>, + message: Option, ) -> JoshResult { let (r, is_new) = create_filtered_commit2( transaction.repo(), original_commit, filtered_parent_ids, filtered_tree, + author, message, false, )?; @@ -620,7 +620,8 @@ fn create_filtered_commit2<'a>( original_commit: &'a git2::Commit, filtered_parent_ids: Vec, filtered_tree: git2::Tree<'a>, - message: Option<(String, String, String)>, + author: Option<(String, String)>, + message: Option, unsign: bool, ) -> JoshResult<(git2::Oid, bool)> { let filtered_parent_commits: Result, _> = filtered_parent_ids @@ -666,6 +667,7 @@ fn create_filtered_commit2<'a>( original_commit, &selected_filtered_parent_commits, &filtered_tree, + author, message, unsign, )?, diff --git a/tests/filter/squash.t b/tests/filter/squash.t index 3a1416c0f..ef888d924 100644 --- a/tests/filter/squash.t +++ b/tests/filter/squash.t @@ -38,9 +38,10 @@ 'git [...] -- [...]' [128] $ git tag tag_a 1d69b7d - $ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered + $ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered [1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - [2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96 + [1] :author="New Author";"new@e.mail" + [2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e $ git log --graph --decorate --pretty=oneline refs/heads/filtered * d8aa5a9937f4f0bd645dbc0b591bae5cd6b6d91b (tag: filtered/tag_a, filtered) refs/tags/tag_a @@ -56,10 +57,11 @@ |/ * 0b4cf6c9efbbda1eada39fa9c1d21d2525b027bb (tag: tag_b) add file1 - $ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered + $ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered [1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - [2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96 - [3] :SQUASH=3953063f3dc58661e9db16f9014aab1e8ec50bf8 + [2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e + [3] :SQUASH=dd8bdf1d78a6cb9ffc9e2a0644a8bf41de56ad36 + [4] :author="New Author";"new@e.mail" $ git log --graph --decorate --pretty=oneline refs/heads/filtered * 5b1a753860ca124024f6dfb4fd018fe7df8beae4 (tag: filtered/tag_a, filtered) refs/tags/tag_a @@ -81,11 +83,12 @@ $ git tag tag_c 975d4c4 - $ josh-filter -s --squash "refs/tags/*" --author "New Author" --email "new@e.mail" --update refs/heads/filtered + $ josh-filter -s --squash "refs/tags/*" :author=\"New\ Author\"\;\"new@e.mail\" --update refs/heads/filtered [1] :SQUASH=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - [2] :SQUASH=e8e83b9c5d2f779f0cea83a6cad68b710a399c96 - [3] :SQUASH=3953063f3dc58661e9db16f9014aab1e8ec50bf8 - [6] :SQUASH=6a132477d438779dbaeb0d68b9aab55786e28dd9 + [2] :SQUASH=10d465cdf297e8062eed54204414414faa63671e + [3] :SQUASH=dd8bdf1d78a6cb9ffc9e2a0644a8bf41de56ad36 + [6] :SQUASH=b2a9a51df03600d3b5858fa7fca044741f88e521 + [9] :author="New Author";"new@e.mail" $ git log --graph --decorate --pretty=oneline refs/heads/filtered * 9fe45cb2bead844630852ab338ecd8e073f8ba50 (tag: filtered/tag_a, filtered) refs/tags/tag_a