Skip to content

Commit

Permalink
cli: Add an option to diff to output only paths.
Browse files Browse the repository at this point in the history
  • Loading branch information
fowles committed Jun 19, 2024
1 parent 3e7ad4d commit 8255186
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* New command `jj branch move` let you update branches by name pattern or source
revision.

* New diff option `jj diff --name-only` allows for easier shell scripting.

### Fixed bugs

## [0.18.0] - 2024-06-05
Expand Down
29 changes: 28 additions & 1 deletion cli/src/diff_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const DEFAULT_CONTEXT_LINES: usize = 3;

#[derive(clap::Args, Clone, Debug)]
#[command(next_help_heading = "Diff Formatting Options")]
#[command(group(clap::ArgGroup::new("short-format").args(&["summary", "stat", "types"])))]
#[command(group(clap::ArgGroup::new("short-format").args(&["summary", "stat", "types", "name_only"])))]
#[command(group(clap::ArgGroup::new("long-format").args(&["git", "color_words", "tool"])))]
pub struct DiffFormatArgs {
/// For each path, show only whether it was modified, added, or deleted
Expand All @@ -66,6 +66,12 @@ pub struct DiffFormatArgs {
/// Git submodule.
#[arg(long)]
pub types: bool,
/// For each path, show only its path
///
/// Typically useful for shell commands like:
/// `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
#[arg(long)]
pub name_only: bool,
/// Show a Git-format diff
#[arg(long)]
pub git: bool,
Expand All @@ -85,6 +91,7 @@ pub enum DiffFormat {
Summary,
Stat,
Types,
NameOnly,
Git { context: usize },
ColorWords { context: usize },
Tool(Box<ExternalMergeTool>),
Expand Down Expand Up @@ -126,6 +133,7 @@ fn diff_formats_from_args(
let mut formats = [
(args.summary, DiffFormat::Summary),
(args.types, DiffFormat::Types),
(args.name_only, DiffFormat::NameOnly),
(
args.git,
DiffFormat::Git {
Expand Down Expand Up @@ -176,6 +184,7 @@ fn default_diff_format(
match name.as_ref() {
"summary" => Ok(DiffFormat::Summary),
"types" => Ok(DiffFormat::Types),
"name-only" => Ok(DiffFormat::NameOnly),
"git" => Ok(DiffFormat::Git {
context: num_context_lines.unwrap_or(DEFAULT_CONTEXT_LINES),
}),
Expand Down Expand Up @@ -251,6 +260,10 @@ impl<'a> DiffRenderer<'a> {
let tree_diff = from_tree.diff_stream(to_tree, matcher);
show_types(formatter, tree_diff, path_converter)?;
}
DiffFormat::NameOnly => {
let tree_diff = from_tree.diff_stream(to_tree, matcher);
show_names(formatter, tree_diff, path_converter)?;
}
DiffFormat::Git { context } => {
let tree_diff = from_tree.diff_stream(to_tree, matcher);
show_git_diff(repo, formatter, *context, tree_diff)?;
Expand Down Expand Up @@ -1105,3 +1118,17 @@ fn diff_summary_char(value: &MergedTreeValue) -> char {
}
}
}

pub fn show_names(
formatter: &mut dyn Formatter,
mut tree_diff: TreeDiffStream,
path_converter: &RepoPathUiConverter,
) -> io::Result<()> {
async {
while let Some((repo_path, _)) = tree_diff.next().await {
writeln!(formatter, "{}", path_converter.format_file_path(&repo_path))?;
}
Ok(())
}
.block_on()
}
15 changes: 15 additions & 0 deletions cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,9 @@ With the `--from` and/or `--to` options, shows the difference from/to the given
* `--types` — For each path, show only its type before and after
The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule.
* `--name-only` — For each path, show only its path
Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
* `--git` — Show a Git-format diff
* `--color-words` — Show a word-level diff with changes indicated only by color
* `--tool <TOOL>` — Generate diff by external command
Expand Down Expand Up @@ -1038,6 +1041,9 @@ This excludes changes from other commits by temporarily rebasing `--from` onto `
* `--types` — For each path, show only its type before and after
The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule.
* `--name-only` — For each path, show only its path
Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
* `--git` — Show a Git-format diff
* `--color-words` — Show a word-level diff with changes indicated only by color
* `--tool <TOOL>` — Generate diff by external command
Expand Down Expand Up @@ -1076,6 +1082,9 @@ Spans of revisions that are not included in the graph per `--revisions` are rend
* `--types` — For each path, show only its type before and after
The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule.
* `--name-only` — For each path, show only its path
Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
* `--git` — Show a Git-format diff
* `--color-words` — Show a word-level diff with changes indicated only by color
* `--tool <TOOL>` — Generate diff by external command
Expand Down Expand Up @@ -1185,6 +1194,9 @@ Name is derived from Merciual's obsolescence markers.
* `--types` — For each path, show only its type before and after
The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule.
* `--name-only` — For each path, show only its path
Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
* `--git` — Show a Git-format diff
* `--color-words` — Show a word-level diff with changes indicated only by color
* `--tool <TOOL>` — Generate diff by external command
Expand Down Expand Up @@ -1592,6 +1604,9 @@ Show commit description and changes in a revision
* `--types` — For each path, show only its type before and after
The diff is shown as two letters. The first letter indicates the type before and the second letter indicates the type after. '-' indicates that the path was not present, 'F' represents a regular file, `L' represents a symlink, 'C' represents a conflict, and 'G' represents a Git submodule.
* `--name-only` — For each path, show only its path
Typically useful for shell commands like: `jj diff -r @- --name_only | xargs perl -pi -e's/OLD/NEW/g`
* `--git` — Show a Git-format diff
* `--color-words` — Show a word-level diff with changes indicated only by color
* `--tool <TOOL>` — Generate diff by external command
Expand Down
28 changes: 28 additions & 0 deletions cli/tests/test_diff_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,34 @@ fn test_diff_types() {
}
}

#[test]
fn test_diff_name_only() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("deleted"), "d").unwrap();
std::fs::write(repo_path.join("modified"), "m").unwrap();
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff", "--name-only"]), @r###"
deleted
modified
"###);
test_env.jj_cmd_ok(&repo_path, &["commit", "-mfirst"]);
std::fs::remove_file(repo_path.join("deleted")).unwrap();
std::fs::write(repo_path.join("modified"), "mod").unwrap();
std::fs::write(repo_path.join("added"), "add").unwrap();
std::fs::create_dir(repo_path.join("sub")).unwrap();
std::fs::write(repo_path.join("sub/added"), "sub/add").unwrap();
insta::assert_snapshot!(test_env.jj_cmd_success(&repo_path, &["diff", "--name-only"]).replace("\\", "/"),
@r###"
added
deleted
modified
sub/added
"###);
}

#[test]
fn test_diff_bad_args() {
let test_env = TestEnvironment::default();
Expand Down

0 comments on commit 8255186

Please sign in to comment.