-
Notifications
You must be signed in to change notification settings - Fork 349
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cli: add
--author
argument for commit
and describe
- Loading branch information
Showing
7 changed files
with
192 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use jj_lib::backend::Signature; | ||
use jj_lib::object_id::ObjectId; | ||
use jj_lib::repo::Repo; | ||
use tracing::instrument; | ||
|
@@ -22,6 +23,7 @@ use crate::command_error::CommandError; | |
use crate::description_util::description_template; | ||
use crate::description_util::edit_description; | ||
use crate::description_util::join_message_paragraphs; | ||
use crate::text_util::parse_author; | ||
use crate::ui::Ui; | ||
|
||
/// Update the description and create a new change on top. | ||
|
@@ -50,6 +52,16 @@ pub(crate) struct CommitArgs { | |
/// $ JJ_USER='Foo Bar' [email protected] jj commit --reset-author | ||
#[arg(long)] | ||
reset_author: bool, | ||
/// Set author to the provided string | ||
/// | ||
/// This changes author name and email while retaining author | ||
/// timestamp for non-discardable commits. | ||
#[arg( | ||
long, | ||
conflicts_with = "reset_author", | ||
value_parser = parse_author | ||
)] | ||
author: Option<(String, String)>, | ||
} | ||
|
||
#[instrument(skip_all)] | ||
|
@@ -106,6 +118,14 @@ new working-copy commit. | |
if args.reset_author { | ||
commit_builder.set_author(commit_builder.committer().clone()); | ||
} | ||
if let Some((name, email)) = args.author.clone() { | ||
let new_author = Signature { | ||
name, | ||
email, | ||
timestamp: commit_builder.author().timestamp.clone(), | ||
}; | ||
commit_builder.set_author(new_author); | ||
} | ||
|
||
let description = if !args.message_paragraphs.is_empty() { | ||
join_message_paragraphs(&args.message_paragraphs) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ use std::io; | |
use std::io::Read; | ||
|
||
use itertools::Itertools; | ||
use jj_lib::backend::Signature; | ||
use jj_lib::commit::CommitIteratorExt; | ||
use jj_lib::object_id::ObjectId; | ||
use tracing::instrument; | ||
|
@@ -30,6 +31,7 @@ use crate::description_util::edit_description; | |
use crate::description_util::edit_multiple_descriptions; | ||
use crate::description_util::join_message_paragraphs; | ||
use crate::description_util::ParsedBulkEditMessage; | ||
use crate::text_util::parse_author; | ||
use crate::ui::Ui; | ||
|
||
/// Update the change description or other metadata | ||
|
@@ -72,6 +74,16 @@ pub(crate) struct DescribeArgs { | |
/// $ JJ_USER='Foo Bar' [email protected] jj describe --reset-author | ||
#[arg(long)] | ||
reset_author: bool, | ||
/// Set author to the provided string | ||
/// | ||
/// This changes author name and email while retaining author | ||
/// timestamp for non-discardable commits. | ||
#[arg( | ||
long, | ||
conflicts_with = "reset_author", | ||
value_parser = parse_author | ||
)] | ||
author: Option<(String, String)>, | ||
} | ||
|
||
#[instrument(skip_all)] | ||
|
@@ -139,6 +151,14 @@ pub(crate) fn cmd_describe( | |
let new_author = commit_builder.committer().clone(); | ||
commit_builder.set_author(new_author); | ||
} | ||
if let Some((name, email)) = args.author.clone() { | ||
let new_author = Signature { | ||
name, | ||
email, | ||
timestamp: commit.author().timestamp.clone(), | ||
}; | ||
commit_builder.set_author(new_author); | ||
} | ||
let temp_commit = commit_builder.write_hidden()?; | ||
Ok((commit.id(), temp_commit)) | ||
}) | ||
|
@@ -194,13 +214,14 @@ pub(crate) fn cmd_describe( | |
// `transform_descendants` below unnecessarily. | ||
let commit_descriptions: HashMap<_, _> = commit_descriptions | ||
.into_iter() | ||
.filter_map(|(commit, new_description)| { | ||
if *new_description == *commit.description() && !args.reset_author { | ||
None | ||
} else { | ||
Some((commit.id(), new_description)) | ||
} | ||
.filter(|(commit, new_description)| { | ||
new_description != commit.description() | ||
|| args.reset_author | ||
|| args.author.as_ref().is_some_and(|(name, email)| { | ||
name != &commit.author().name || email != &commit.author().email | ||
}) | ||
}) | ||
.map(|(commit, new_description)| (commit.id(), new_description)) | ||
.collect(); | ||
|
||
let mut num_described = 0; | ||
|
@@ -225,6 +246,14 @@ pub(crate) fn cmd_describe( | |
let new_author = commit_builder.committer().clone(); | ||
commit_builder = commit_builder.set_author(new_author); | ||
} | ||
if let Some((name, email)) = args.author.clone() { | ||
let new_author = Signature { | ||
name, | ||
email, | ||
timestamp: commit_builder.author().timestamp.clone(), | ||
}; | ||
commit_builder = commit_builder.set_author(new_author); | ||
} | ||
num_described += 1; | ||
} else { | ||
num_rebased += 1; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -261,6 +261,12 @@ pub fn write_wrapped( | |
}) | ||
} | ||
|
||
pub fn parse_author(author: &str) -> Result<(String, String), &'static str> { | ||
let re = regex::Regex::new(r"(?<name>.*?)\s*<(?<email>.+)>$").unwrap(); | ||
let captures = re.captures(author).ok_or("Invalid author string")?; | ||
Ok((captures["name"].to_string(), captures["email"].to_string())) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::io::Write as _; | ||
|
@@ -632,4 +638,33 @@ mod tests { | |
"foo\n", | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_parse_author() { | ||
let expected_name = "Example"; | ||
let expected_email = "[email protected]"; | ||
let parsed = parse_author(&format!("{expected_name} <{expected_email}>")).unwrap(); | ||
assert_eq!( | ||
(expected_name.to_string(), expected_email.to_string()), | ||
parsed | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_parse_author_with_utf8() { | ||
let expected_name = "Ąćęłńóśżź"; | ||
let expected_email = "[email protected]"; | ||
let parsed = parse_author(&format!("{expected_name} <{expected_email}>")).unwrap(); | ||
assert_eq!( | ||
(expected_name.to_string(), expected_email.to_string()), | ||
parsed | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_parse_author_without_name() { | ||
let expected_email = "[email protected]"; | ||
let parsed = parse_author(&format!("<{expected_email}>")).unwrap(); | ||
assert_eq!(("".to_string(), expected_email.to_string()), parsed); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -447,6 +447,9 @@ Update the description and create a new change on top | |
You can use it in combination with the JJ_USER and JJ_EMAIL environment variables to set a different author: | ||
$ JJ_USER='Foo Bar' [email protected] jj commit --reset-author | ||
* `--author <AUTHOR>` — Set author to the provided string | ||
This changes author name and email while retaining author timestamp for non-discardable commits. | ||
|
@@ -600,6 +603,9 @@ Starts an editor to let you edit the description of changes. The editor will be | |
You can use it in combination with the JJ_USER and JJ_EMAIL environment variables to set a different author: | ||
$ JJ_USER='Foo Bar' [email protected] jj describe --reset-author | ||
* `--author <AUTHOR>` — Set author to the provided string | ||
This changes author name and email while retaining author timestamp for non-discardable commits. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,6 +215,7 @@ fn test_commit_with_description_template() { | |
|
||
std::fs::write(workspace_path.join("file1"), "foo\n").unwrap(); | ||
std::fs::write(workspace_path.join("file2"), "bar\n").unwrap(); | ||
std::fs::write(workspace_path.join("file3"), "foobar\n").unwrap(); | ||
|
||
// Only file1 should be included in the diff | ||
test_env.jj_cmd_ok(&workspace_path, &["commit", "file1"]); | ||
|
@@ -230,19 +231,41 @@ fn test_commit_with_description_template() { | |
JJ: Lines starting with "JJ: " (like this one) will be removed. | ||
"###); | ||
|
||
// Timestamp after the reset should be available to the template | ||
test_env.jj_cmd_ok(&workspace_path, &["commit", "--reset-author"]); | ||
// Only file2 with modified author should be included in the diff | ||
test_env.jj_cmd_ok( | ||
&workspace_path, | ||
&[ | ||
"commit", | ||
"--author", | ||
"Another User <[email protected]>", | ||
"file2", | ||
], | ||
); | ||
insta::assert_snapshot!( | ||
std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r###" | ||
std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" | ||
JJ: Author: Test User <test[email protected]> (2001-02-03 08:05:09) | ||
JJ: Author: Another User <another[email protected]> (2001-02-03 08:05:08) | ||
JJ: Committer: Test User <[email protected]> (2001-02-03 08:05:09) | ||
JJ: file2 | 1 + | ||
JJ: 1 file changed, 1 insertion(+), 0 deletions(-) | ||
JJ: Lines starting with "JJ: " (like this one) will be removed. | ||
"###); | ||
"#); | ||
|
||
// Timestamp after the reset should be available to the template | ||
test_env.jj_cmd_ok(&workspace_path, &["commit", "--reset-author"]); | ||
insta::assert_snapshot!( | ||
std::fs::read_to_string(test_env.env_root().join("editor")).unwrap(), @r#" | ||
JJ: Author: Test User <[email protected]> (2001-02-03 08:05:10) | ||
JJ: Committer: Test User <[email protected]> (2001-02-03 08:05:10) | ||
JJ: file3 | 1 + | ||
JJ: 1 file changed, 1 insertion(+), 0 deletions(-) | ||
JJ: Lines starting with "JJ: " (like this one) will be removed. | ||
"#); | ||
} | ||
|
||
#[test] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -525,29 +525,75 @@ fn test_describe_author() { | |
~ | ||
"###); | ||
|
||
// Reset the author for the latest commit (the committer is always reset) | ||
// Change the author for the latest commit (the committer is always reset) | ||
test_env.jj_cmd_ok( | ||
&repo_path, | ||
&[ | ||
"describe", | ||
"--config-toml", | ||
r#"user.name = "Ove Ridder" | ||
user.email = "[email protected]""#, | ||
"--no-edit", | ||
"--reset-author", | ||
"--author", | ||
"Super Seeder <[email protected]>", | ||
], | ||
); | ||
insta::assert_snapshot!(get_signatures(), @r###" | ||
@ Ove Ridder ove.ridder@example.com 2001-02-03 04:05:12.000 +07:00 | ||
│ Ove Ridder ove.ridder@example.com 2001-02-03 04:05:12.000 +07:00 | ||
insta::assert_snapshot!(get_signatures(), @r#" | ||
@ Super Seeder super.seeder@example.com 2001-02-03 04:05:12.000 +07:00 | ||
│ Test User test.user@example.com 2001-02-03 04:05:12.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:09.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:09.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:08.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:08.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:07.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:07.000 +07:00 | ||
~ | ||
"###); | ||
"#); | ||
|
||
// Change the author for multiple commits (the committer is always reset) | ||
test_env.jj_cmd_ok( | ||
&repo_path, | ||
&[ | ||
"describe", | ||
"@---", | ||
"@-", | ||
"--no-edit", | ||
"--author", | ||
"Super Seeder <[email protected]>", | ||
], | ||
); | ||
insta::assert_snapshot!(get_signatures(), @r#" | ||
@ Super Seeder [email protected] 2001-02-03 04:05:12.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Super Seeder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Super Seeder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
~ | ||
"#); | ||
|
||
// Reset the author for the latest commit (the committer is always reset) | ||
test_env.jj_cmd_ok( | ||
&repo_path, | ||
&[ | ||
"describe", | ||
"--config-toml", | ||
r#"user.name = "Ove Ridder" | ||
user.email = "[email protected]""#, | ||
"--no-edit", | ||
"--reset-author", | ||
], | ||
); | ||
insta::assert_snapshot!(get_signatures(), @r#" | ||
@ Ove Ridder [email protected] 2001-02-03 04:05:16.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:16.000 +07:00 | ||
○ Super Seeder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Super Seeder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
~ | ||
"#); | ||
|
||
// Reset the author for multiple commits (the committer is always reset) | ||
test_env.jj_cmd_ok( | ||
|
@@ -563,17 +609,17 @@ fn test_describe_author() { | |
"--reset-author", | ||
], | ||
); | ||
insta::assert_snapshot!(get_signatures(), @r###" | ||
@ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:08.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
○ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
insta::assert_snapshot!(get_signatures(), @r#" | ||
@ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
○ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
○ Test User [email protected] 2001-02-03 04:05:14.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
○ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
│ Ove Ridder [email protected] 2001-02-03 04:05:18.000 +07:00 | ||
~ | ||
"###); | ||
"#); | ||
} | ||
|
||
#[test] | ||
|