Color-words diffs use formatter labels to distinguish removed and
added tokens. When color is disabled, those labels are invisible,
so inline word changes can collapse into unreadable text when
stdout is not a TTY.
Render color-words hunks as separate before and after lines
whenever the formatter cannot emit color. This keeps the default
diff format stable while making piped or redirected output
readable.
Color-words tests that rely on inline display force color output
because inlining is only triggered when color is available, ANSI
sequences are stripped before snapshotting to keep the snapshots
readable.
This does not make redirected diffs into git-format patches.
Users still need --git for patch exchange or tools that require
unified diff input.
Fixes#5894.
Related to #6972.
Adding this based on the feature request in #9102.
There's a question there of whether a convenience flag would be helpful (presumably something like `--git-show-path-prefix`. This PR isn't adding that because I thought `--config=diff.git.show-path-prefix=<value>` might be good enough; i.e., maybe flipping back and forth won't be a common operation and so keeping the `jj diff` options smaller would be better.
Fixes#9102
Assisted-by: Google Antigravity with Gemini
Assisted-by: My AI Tool
Mostly done with OpenCode and Claude Sonnet 4.6 with the following prompt,
and reviewed manually:
Replace the Result.unwrap with the ? operator in test functions.
While doing that, make sure to:
* Add TestResult as return type in the test functions where you replace
unwrap by the ? operator, and Ok(()) at the end.
* Do the replacement only in method with the `#[test]` decorator.
* Don't replace unwraps in closures.
* Don't replace Option.unwrap.
* Be careful to not change the insta snapshot references.
* Run the tests each time you're done with a file.
* Keep the unwraps that you can't replace with the ? operator.
Note that:
* You can identify all the Result.unwrap locations with this command:
cargo clippy --tests --message-format=short -- -W clippy::unwrap_used 2>&1 | grep / | grep Result | grep <filename>
* Begin with the file with the most Result.unwrap in them as shown by
this command:
cargo clippy --tests --message-format=short -- -W clippy::unwrap_used 2>&1 | grep Result | cut -d: -f1 | sort | uniq -c | sort -nr
* Some non test files have inline tests.
Before this PR:
❯ cargo clippy --tests --message-format=short -- -W clippy::unwrap_used 2>&1 | grep Result | wc -l
3973
After this PR:
❯ cargo clippy --tests --message-format=short -- -W clippy::unwrap_used 2>&1 | grep Result | wc -l
1064
Currently, checking out a commit with conflicts in a colocated workspace
causes many editors to show all existing files as added since they
aren't present in the Git HEAD commit. Using the tree of the first side
of the commit as a base tree and then adding the '.jjconflict-*' trees
on top of it would cause any files identical to the first tree to show
as unchanged, matching Git's conflict behavior.
One potential downside to this change is that it becomes harder for a
user to notice if they incorrectly check out a conflicted commit using
`git switch`, since previously all of their files would've disappeared
so it would be more difficult to ignore. However, I think this could be
solved a different way, such as by adding a warning when snapshotting if
'.jjconflict' files are detected. Keeping the files from the first
tree also has the benefit that '.gitignore' files will still be present,
meaning that when a user does `jj abandon` to recover, it won't delete
their ignored files.
Using 'JJ-CONFLICT-README' as the name for the readme file instead of
'README' makes it more clear that this file is related to the
'.jjconflict-*' trees, since now the repo's actual README file might be
present as well in the tree.
Dependabot couldn't handle updates to 'clap' since it slightly changes
the output format of some tests, so we have to do that.
'rand_chacha' v0.10.0 was not included in this diff because it requires
a larger set of changes (and rand itself is still 0.9.0?)
Signed-off-by: Austin Seipp <aseipp@pobox.com>
Commands `jj log`, `jj evolog`, and `jj op log` automatically added a
terminating newline when the expanded template did not include one in graph
mode. No-graph mode did not do this, so the expanded template could combine with
any following content (diff, op changes, etc) in confusing or problematic ways.
Instead of trying to compensate in all cases, remove the auto-fixups. Users
should confirm their custom templates still expand correctly for their needs.
It would be good to include the word "divergent" in the log when a
change is divergent, since users are often unsure what's happening when
they see a divergent change, and giving them a term to search for would
be helpful. However, I don't think it looks good to put this label next
to the change ID itself if both are the same color, since it ends up
being hard to distinguish from the change offset at a glance. Also,
putting the label next to the change ID also messes up the alignment of
fields in the log. Therefore, I think it looks better to put the
"divergent" label at the end of the line.
Since divergence and hidden commits are similar, it makes sense for both
labels to be in the same place, so I also moved the hidden label to the
end for consistency.
One downside is that the labels are less obviously connected with the
change ID itself due to them being farther apart. I think this could be
fine, since they are still visually connected by being the same color.
An example with parents `rtsqusxu` and `ysrnknol`:
```
<<<<<<< conflict 1 of 1
%%%%%%% diff from: vpxusssl 38d49363 "description of base"
\\\\\\\ to: rtsqusxu 2768b0b9 "description of left"
-base
+left
+++++++ ysrnknol 7a20f389 "description of right"
right
>>>>>>> conflict 1 of 1 ends
```
Conflict labels will generally start with lowercase change IDs, so
making all of the text lowercase makes it more consistent. I also
removed the "contents of" text, since conflict labels will already be
long enough, and this text doesn't add anything. Similarly, I removed
the "(conflict 1 of 1)" note from the Git conflict markers since Git
doesn't include this information, and including it would result in extra
long lines once we add conflict labels.
This will help notice small hunks in inlined diff lines. Not all terminals would
support "dim" attribute, but I think that's okay since the diff output should be
readable with/without this change.
Closes#5140
As a follow-up to #8115, this moves all references in the codebase to use the new website.
I didn't update the older CHANGELOG entries because I figured they're intended
to be immutable.
Deprecation warnings will be emitted for default "substring:" patterns. This
change will suppress them. Since "glob:" will be the new default, I made these
tests use "glob:" when both "exact:" and "glob:" work.
Tests for the revset filter functions aren't updated.
We could allow merge edges coming into the range of commits but it's
probably a rare use case and it's a bit complicated to implement while
also preserving the parent order. Simply disallowing such cases for
now is better than producing incorrect results.
Not setting `diff-args` is equivalent to `diff-args=["$left",
"$right"]`, which I also documented here.
I couldn't decide whether the new error should be part of
`DiffRenderError`, `DiffGenerateError`, or `MergeToolError`. Since the
treatment of diff formatters is already very different from other merge
tools, I just made it a CommandError for now.
Previously, the computation for the available display width
included a padding constant, but this value was then used as
an upper bound for the width of the bar. This meant the bar
would never fill the available screen width.
I had a report from a user at Google who was confused about a config
deprecation message because they had forgotten that they set a
repo-level config. This patch includes the source level in the warning
message. Hopefully that's sufficient. We could of course print the
path too, but that would make the message much longer so we would have
to split it up on two lines and I'm not sure it's worth it.
This is just for completeness. I don't think this is practically useful, but the
:<format> syntax should work in both config files and command arguments.
This allows users to override the external tool set in ~/.jjconfig.toml. The
config variable is renamed to ui.diff-formatter to be consistent with the other
diff/merge editor settings.
--tool=:<format> support will be added separately.
Closes#3327
The name of the temporary directory that is created when running
external diff tools can add significant noise to a diff if the tool
displays paths prominently.
Change the behaviour so that we chdir to the temporary directory before
running the tool, with a setting to revert to the previous behaviour.
Closes#5801
I was wondering whether this is presentation issue or not, and I think it is a
matter of DiffLineIterator. For matching hunks, DiffLineIterator flushes the
current_line buffer and bumps the line numbers for the next line. This should
guarantee that there are no blank DiffLine to be queued. However, for different
hunks, only the left line number can be bumped in the first loop, so there may
be an empty-looking hunk having the same right line number.
Closes#6471
We haven't had any reports of problems from people who opted in. Since
it's early in the release cycle now, let's now test it on everyone who
builds from head, so we get almost a month of testing from those
people before it's enabled by default in a released version.
This impacts lots of test cases because the change-id header is added
to the Git commit. Most are uninteresting. `test_git_fetch` now sees
some divergent changes where it used to see only divergent bookmarks,
which makes sense.
The original idea was to flatten left/right conflict trees and pair up adjacent
negative/positive terms. For example, diff(A, B-C+D) could be rendered as
diff(A, B) and diff(C, D). The problem of this formalization is that one of the
diff pairs is often empty (because e.g. A=B), so the context is fully omitted.
The resulting diff(C, D) doesn't provide any notion why the hunk is conflicted,
and how it is different from A.
Instead, this patch implements diffs in which each left/right pair is compared.
In the example above, the left terms are padded, and the diffs are rendered as
diff(A, B), diff(-A, -C), diff(A, D). This appears to be working reasonably well
so long as either side is resolved or both sides have the same numbers of terms.
Closes#4062
This helps extract hunk rendering function for non-materialized color-words
diffs. In conflict hunk, an identical diff pair will be omitted with "..."
marker.
This patch introduces a subtle behavior change when "ignore whitespace" options
are used. Before, "..." wouldn't be printed if contents differ only in
whitespace. I don't think the new behavior is bad because the file header says
"Modified regular file" in that case.