Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
cli/diff: Use clap
Merged lorenz opened 7 months ago

See issue/7fb03f234030b91c38cc4f5b48bd30cf5fd6a1de.

4 files changed +122 -249 532e5a0d 72cf3d19
modified crates/radicle-cli/examples/rad-diff.md
@@ -32,76 +32,74 @@ $ git commit -m "Make changes"

```
$ rad diff HEAD^ HEAD
-
╭────────────────────────────────────────────╮
-
│ README -> README.md ❲moved❳                │
-
╰────────────────────────────────────────────╯
-

-
╭────────────────────────────────────────────╮
-
│ main.c +6 ❲created❳                        │
-
├────────────────────────────────────────────┤
-
│ @@ -0,0 +1,6 @@                            │
-
│      1     + #include <stdio.h>            │
-
│      2     +                               │
-
│      3     + int main(void) {              │
-
│      4     +     printf("Hello World!/n"); │
-
│      5     +     return 0;                 │
-
│      6     + }                             │
-
╰────────────────────────────────────────────╯
-

+
diff --git a/README b/README.md
+
similarity index 100%
+
rename from README
+
rename to README.md
+
diff --git a/main.c b/main.c
+
new file mode 100644
+
index 0000000..aae4e0e
+
--- /dev/null
+
+++ b/main.c
+
@@ -0,0 +1,6 @@
+
+#include <stdio.h>
+
+
+
+int main(void) {
+
+    printf("Hello World!/n");
+
+    return 0;
+
+}
```

```
$ sed -i 's/Hello World/Hello Radicle/' main.c
$ rad diff
-
╭──────────────────────────────────────────────╮
-
│ main.c -1 +1                                 │
-
├──────────────────────────────────────────────┤
-
│ @@ -1,6 +1,6 @@                              │
-
│ 1    1       #include <stdio.h>              │
-
│ 2    2                                       │
-
│ 3    3       int main(void) {                │
-
│ 4          -     printf("Hello World!/n");   │
-
│      4     +     printf("Hello Radicle!/n"); │
-
│ 5    5           return 0;                   │
-
│ 6    6       }                               │
-
╰──────────────────────────────────────────────╯
-

+
diff --git a/main.c b/main.c
+
index aae4e0e..a3ed869 100644
+
--- a/main.c
+
+++ b/main.c
+
@@ -1,6 +1,6 @@
+
 #include <stdio.h>
+
 
+
 int main(void) {
+
-    printf("Hello World!/n");
+
+    printf("Hello Radicle!/n");
+
     return 0;
+
 }
```

```
$ git add main.c
$ rad diff
$ rad diff --staged
-
╭──────────────────────────────────────────────╮
-
│ main.c -1 +1                                 │
-
├──────────────────────────────────────────────┤
-
│ @@ -1,6 +1,6 @@                              │
-
│ 1    1       #include <stdio.h>              │
-
│ 2    2                                       │
-
│ 3    3       int main(void) {                │
-
│ 4          -     printf("Hello World!/n");   │
-
│      4     +     printf("Hello Radicle!/n"); │
-
│ 5    5           return 0;                   │
-
│ 6    6       }                               │
-
╰──────────────────────────────────────────────╯
-

+
diff --git a/main.c b/main.c
+
index aae4e0e..a3ed869 100644
+
--- a/main.c
+
+++ b/main.c
+
@@ -1,6 +1,6 @@
+
 #include <stdio.h>
+
 
+
 int main(void) {
+
-    printf("Hello World!/n");
+
+    printf("Hello Radicle!/n");
+
     return 0;
+
 }
```

```
$ git rm -f -q main.c
$ rad diff --staged
-
╭────────────────────────────────────────────╮
-
│ main.c -6 ❲deleted❳                        │
-
├────────────────────────────────────────────┤
-
│ @@ -1,6 +0,0 @@                            │
-
│ 1          - #include <stdio.h>            │
-
│ 2          -                               │
-
│ 3          - int main(void) {              │
-
│ 4          -     printf("Hello World!/n"); │
-
│ 5          -     return 0;                 │
-
│ 6          - }                             │
-
╰────────────────────────────────────────────╯
-

+
diff --git a/main.c b/main.c
+
deleted file mode 100644
+
index aae4e0e..0000000
+
--- a/main.c
+
+++ /dev/null
+
@@ -1,6 +0,0 @@
+
-#include <stdio.h>
+
-
+
-int main(void) {
+
-    printf("Hello World!/n");
+
-    return 0;
+
-}
```

For now, copies are not detected.
@@ -112,13 +110,13 @@ $ mkdir docs
$ cp README.md docs/README.md
$ git add docs
$ rad diff --staged
-
╭─────────────────────────────╮
-
│ docs/README.md +1 ❲created❳ │
-
├─────────────────────────────┤
-
│ @@ -0,0 +1,1 @@             │
-
│      1     + Hello World!   │
-
╰─────────────────────────────╯
-

+
diff --git a/docs/README.md b/docs/README.md
+
new file mode 100644
+
index 0000000..980a0d5
+
--- /dev/null
+
+++ b/docs/README.md
+
@@ -0,0 +1 @@
+
+Hello World!
$ git reset
$ git checkout .
```
@@ -129,10 +127,9 @@ Empty file.
$ touch EMPTY
$ git add EMPTY
$ rad diff --staged
-
╭─────────────────╮
-
│ EMPTY ❲created❳ │
-
╰─────────────────╯
-

+
diff --git a/EMPTY b/EMPTY
+
new file mode 100644
+
index 0000000..e69de29
$ git reset
$ git checkout .
```
@@ -142,10 +139,9 @@ File mode change.
```
$ chmod +x README.md
$ rad diff
-
╭───────────────────────────────────────────╮
-
│ README.md 100644 -> 100755 ❲mode changed❳ │
-
╰───────────────────────────────────────────╯
-

+
diff --git a/README.md b/README.md
+
old mode 100644
+
new mode 100755
$ git reset -q
$ git checkout .
```
@@ -157,8 +153,8 @@ $ touch file.bin
$ truncate -s 8 file.bin
$ git add file.bin
$ rad diff --staged
-
╭─────────────────────────────╮
-
│ file.bin ❲binary❳ ❲created❳ │
-
╰─────────────────────────────╯
-

+
diff --git a/file.bin b/file.bin
+
new file mode 100644
+
index 0000000..1b1cb4d
+
Binary files /dev/null and b/file.bin differ
```
modified crates/radicle-cli/examples/rad-patch-diff.md
@@ -11,13 +11,13 @@ $ git push rad HEAD:refs/patches
```
```
$ rad patch diff 147309e
-
╭───────────────────────────╮
-
│ README.md +1 ❲created❳    │
-
├───────────────────────────┤
-
│ @@ -0,0 +1,1 @@           │
-
│      1     + Hello World! │
-
╰───────────────────────────╯
-

+
diff --git a/README.md b/README.md
+
new file mode 100644
+
index 0000000..980a0d5
+
--- /dev/null
+
+++ b/README.md
+
@@ -0,0 +1 @@
+
+Hello World!
```

If we add another file and update the patch, we can see it in the diff.
@@ -32,20 +32,20 @@ $ git push -f
```
```
$ rad patch diff 147309e
-
╭─────────────────────────────╮
-
│ RADICLE.md +1 ❲created❳     │
-
├─────────────────────────────┤
-
│ @@ -0,0 +1,1 @@             │
-
│      1     + Hello Radicle! │
-
╰─────────────────────────────╯
-

-
╭─────────────────────────────╮
-
│ README.md +1 ❲created❳      │
-
├─────────────────────────────┤
-
│ @@ -0,0 +1,1 @@             │
-
│      1     + Hello World!   │
-
╰─────────────────────────────╯
-

+
diff --git a/RADICLE.md b/RADICLE.md
+
new file mode 100644
+
index 0000000..e517184
+
--- /dev/null
+
+++ b/RADICLE.md
+
@@ -0,0 +1 @@
+
+Hello Radicle!
+
diff --git a/README.md b/README.md
+
new file mode 100644
+
index 0000000..980a0d5
+
--- /dev/null
+
+++ b/README.md
+
@@ -0,0 +1 @@
+
+Hello World!
```

Buf if we only want to see the changes from the first revision, we can do that
@@ -53,11 +53,11 @@ too.

```
$ rad patch diff 147309e --revision 147309e
-
╭───────────────────────────╮
-
│ README.md +1 ❲created❳    │
-
├───────────────────────────┤
-
│ @@ -0,0 +1,1 @@           │
-
│      1     + Hello World! │
-
╰───────────────────────────╯
-

+
diff --git a/README.md b/README.md
+
new file mode 100644
+
index 0000000..980a0d5
+
--- /dev/null
+
+++ b/README.md
+
@@ -0,0 +1 @@
+
+Hello World!
```
modified crates/radicle-cli/src/commands/diff.rs
@@ -1,153 +1,14 @@
-
use std::ffi::OsString;
+
use std::{ffi::OsString, process};

-
use anyhow::anyhow;
-

-
use radicle::git;
-
use radicle::rad;
-
use radicle_surf as surf;
-

-
use crate::git::pretty_diff::ToPretty as _;
-
use crate::git::Rev;
-
use crate::terminal as term;
-
use crate::terminal::args::{Args, Error, Help};
-
use crate::terminal::highlight::Highlighter;
-

-
pub const HELP: Help = Help {
-
    name: "diff",
-
    description: "Show changes between commits",
-
    version: env!("RADICLE_VERSION"),
-
    usage: r#"
-
Usage
-

-
    rad diff [<commit>] [--staged] [<option>...]
-
    rad diff <commit> [<commit>] [<option>...]
-

-
    This command is meant to operate as closely as possible to `git diff`,
-
    except its output is optimized for human-readability.
-

-
Options
-

-
    --unified, -U   Context lines to show (default: 5)
-
    --staged        View staged changes
-
    --color         Force color output
-
    --help          Print help
-
"#,
-
};
-

-
pub struct Options {
-
    pub commits: Vec<Rev>,
-
    pub staged: bool,
-
    pub unified: usize,
-
    pub color: bool,
-
}
-

-
impl Args for Options {
-
    fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
-
        use lexopt::prelude::*;
-

-
        let mut parser = lexopt::Parser::from_args(args);
-
        let mut commits = Vec::new();
-
        let mut staged = false;
-
        let mut unified = 5;
-
        let mut color = false;
-

-
        while let Some(arg) = parser.next()? {
-
            match arg {
-
                Long("unified") | Short('U') => {
-
                    let val = parser.value()?;
-
                    unified = term::args::number(&val)?;
-
                }
-
                Long("staged") | Long("cached") => staged = true,
-
                Long("color") => color = true,
-
                Long("help") | Short('h') => return Err(Error::Help.into()),
-
                Value(val) => {
-
                    let rev = term::args::rev(&val)?;
-

-
                    commits.push(rev);
-
                }
-
                _ => anyhow::bail!(arg.unexpected()),
-
            }
-
        }
-

-
        Ok((
-
            Options {
-
                commits,
-
                staged,
-
                unified,
-
                color,
-
            },
-
            vec![],
-
        ))
-
    }
-
}
-

-
pub fn run(options: Options, _ctx: impl term::Context) -> anyhow::Result<()> {
+
pub fn run(args: Vec<OsString>) -> anyhow::Result<()> {
    crate::warning::deprecated("rad diff", "git diff");

-
    let repo = rad::repo()?;
-
    let oids = options
-
        .commits
-
        .into_iter()
-
        .map(|rev| {
-
            repo.revparse_single(rev.as_str())
-
                .map_err(|e| anyhow!("unknown object {rev}: {e}"))
-
                .and_then(|o| {
-
                    o.into_commit()
-
                        .map_err(|_| anyhow!("object {rev} is not a commit"))
-
                })
-
        })
-
        .collect::<Result<Vec<_>, _>>()?;
-

-
    let mut opts = git::raw::DiffOptions::new();
-
    opts.patience(true)
-
        .minimal(true)
-
        .context_lines(options.unified as u32);
-

-
    let mut find_opts = git::raw::DiffFindOptions::new();
-
    find_opts.exact_match_only(true);
-
    find_opts.all(true);
-

-
    let mut diff = match oids.as_slice() {
-
        [] => {
-
            if options.staged {
-
                let head = repo.head()?.peel_to_tree()?;
-
                // HEAD vs. index.
-
                repo.diff_tree_to_index(Some(&head), None, Some(&mut opts))
-
            } else {
-
                // Working tree vs. index.
-
                repo.diff_index_to_workdir(None, None)
-
            }
-
        }
-
        [commit] => {
-
            let commit = commit.tree()?;
-
            if options.staged {
-
                // Commit vs. index.
-
                repo.diff_tree_to_index(Some(&commit), None, Some(&mut opts))
-
            } else {
-
                // Commit vs. working tree.
-
                repo.diff_tree_to_workdir(Some(&commit), Some(&mut opts))
-
            }
-
        }
-
        [left, right] => {
-
            // Commit vs. commit.
-
            let left = left.tree()?;
-
            let right = right.tree()?;
-

-
            repo.diff_tree_to_tree(Some(&left), Some(&right), Some(&mut opts))
-
        }
-
        _ => {
-
            anyhow::bail!("Too many commits given. See `rad diff --help` for usage.");
-
        }
-
    }?;
-
    diff.find_similar(Some(&mut find_opts))?;
-

-
    term::Paint::force(options.color);
-

-
    let diff = surf::diff::Diff::try_from(diff)?;
-
    let mut hi = Highlighter::default();
-
    let pretty = diff.pretty(&mut hi, &(), &repo);
+
    let mut child = process::Command::new("git")
+
        .arg("diff")
+
        .args(args)
+
        .spawn()?;

-
    crate::pager::run(pretty)?;
+
    let exit_status = child.wait()?;

-
    Ok(())
+
    process::exit(exit_status.code().unwrap_or(1));
}
modified crates/radicle-cli/src/main.rs
@@ -49,6 +49,18 @@ enum Commands {
    Clean(clean::Args),
    Clone(clone::Args),
    Debug(debug::Args),
+

+
    /// This command is deprecated and delegates to `git diff`.
+
    /// Even before it was deprecated, it was not printed by
+
    /// `rad -h`, so it is also hidden.
+
    ///
+
    /// Since it is hidden, it makes no sense to add `about`
+
    /// for the command listing, and since it is external,
+
    /// `--help` will delegate to `git diff --help` it makes
+
    /// no sense to add `long_about` for `rad diff --help`.
+
    #[command(external_subcommand, hide = true)]
+
    Diff(Vec<OsString>),
+

    Fork(fork::Args),
    Issue(issue::Args),
    Path(path::Args),
@@ -206,7 +218,11 @@ pub(crate) fn run_other(exe: &str, args: &[OsString]) -> Result<(), Option<anyho
            term::run_command_args::<config::Options, _>(config::HELP, config::run, args.to_vec());
        }
        "diff" => {
-
            term::run_command_args::<diff::Options, _>(diff::HELP, diff::run, args.to_vec());
+
            if let Some(Commands::Diff(mut args)) = CliArgs::parse().command {
+
                debug_assert_eq!(args[0], "diff");
+
                args.remove(0);
+
                return diff::run(args).map_err(Some);
+
            }
        }
        "debug" => {
            if let Some(Commands::Debug(args)) = CliArgs::parse().command {