This fixes the problem that patching would stop at the first file that has a
conflict. We always want to patch all files.
Also, it's faster for large patches, and the code is a little bit simpler too.
The patch contains changes to two files; the first one conflicts, the second
doesn't. Note how it only applies changes to the first file at this point in the
branch; we'll fix this in the next commit.
This test would fail on master for multiple reasons.
All callers in this file now use reverseOnGenerate=false and
keepOriginalHeader=true, so hard-code that in the call to ModifiedPatchForLines
and get rid of the parameters.
The loop is pointless for two reasons:
- git apply --3way has this fallback built in already. If it can't do a
three-way merge, it will fall back to applying the patch normally.
- However, the only situation where it does this is when it can't do a 3-way
merge at all because it can't find the necessary ancestor blob. This can only
happen if you transfer a patch between different repos that don't have the
same blobs available; we are applying the patch to the same repo that is was
just generated from, so a 3-way merge is always possible. (Now that we fixed
the bug in the previous commit, that is.)
But the retry loop is not only pointless, it was actually harmful, because when
a 3-way patch fails with a conflict, git will put conflict markers in the
patched file and then exit with a non-zero exit status. So the retry loop would
try to patch the already patched file again, and this almost certainly fails,
but with a cryptic error message such as "error: main.go: does not exist in
index".
There's no reason to have two different ways of applying patches for whole-file
patches and partial patches; use --reverse for both. Not only does this simplify
the code a bit, but it fixes an actual problem: when reverseOnGenerate and
keepOriginalHeader are both true, the generated patch header is broken (the two
blobs in the line `index 6d1959b..6dc5f84 100644` are swapped). Git fails to do
a proper three-way merge in that case, as it expects the first of the two blobs
to be the common ancestor.
It would be possible to fix this by extending ModifiedPatchForLines to swap the
two blobs in this case; but this would prevent us from concatenating all patches
and apply them in one go, which we are going to do later in the branch.
We are going to add one more flag in the next commit.
Note that we are not using the struct inside patch_manager.go; we keep passing
the individual flags there. The reason for this will become more obvious later
in this branch.
This is the working tree state at the time the model commits were loaded. This
avoids a visual glitch with the "You Are Here" label appearing at times when it
is not supposed to.
Instead, derive it from context at display time (if we're rebasing, it's the
first non-todo commit). This fixes the problem that unfolding the current
commit's files in the local commits panel would show junk in the frame's title.
Along the way we make sure to only display the "<--- YOU ARE HERE" string in the
local commits panel; previously it would show for the top commit of a branch or
tag if mid-rebase.
If you ran this test enough times it would eventually fail; this happened
whenever the resulting squashed commit had a sha that happened to start with
"02". We test that "commit 02" does not appear in the diff window, but in that
case it did, at the very top of the window.
A better fix might be to change the commit message that we use in CreateNCommits
to something other than "commit XY", but that would require touching tons of
tests, so this is the easier fix.
It's not so much the total number of commits that matters here, it's just
whether we are on the first one. (This includes the other condition.)
This allows us to get rid of the condition in rebase.go.
Instead of rebasing from the commit below the current one and then setting the
current one to "edit", we rebase from the current one and insert a "break" after
it. In most cases the behavior is exactly the same as before, except that the
new method also works if the current commit is a merge commit. This is useful if
you want to create a new commit at the very beginning of your branch (by editing
the last commit before your branch).
There are two reasons for doing this:
1. The view cursor position is often out of sync with the selected line; see
first commit of this branch.
2. The highlighting is already turned off when the view loses focus, and never
turned back on thereafter. So just turn it off from the start then.
We already have this very convenient behavior of jumping to the next stageable
line after staging something. However, while this worked well for staging
single lines or hunks, it didn't work correctly when staging a range of lines;
in this case we want to start searching from the first line of the range.
While we try to keep the view's cursor position in sync with the context state's
selectedLineIdx (at least when pressing up or down), there are enough situations
where the two run out of sync; for example when initially opening the view, or
after staging a hunk, or when scrolling the view using the wheel. While it would
be possible to fix these situations to keep them always in sync, it doesn't seem
worth it, because the view's cursor position isn't really used for anything
else. So we rather special-case the SelectedLine/SelectedLineIdx functions of
ViewDriver to query the context state's selectedLineIdx directly if it is a
patch explorer context.
For users who have the rebase.autoSquash git config set to true, any regular
rebase will squash fixups in addition to rebasing. Not good -- we'll fix that in
the next commit.
A global ~/.gitconfig file can have influence on how integration tests behave;
in my case, I had the option "merge.conflictStyle" set to "diff3", which made
the integration test "cherry_pick_conflict" fail because the diff was different
from what the test expected.
Make this more robust by telling git to ignore the global config file when
running tests.
There's no need for refreshing anything; all that's needed is to re-focus the
selected list item. This way it will also work in other panels, which we are
about to add in the next commit.
I noticed that `$GIT_SEQUENCE_EDITOR` is overridden in `PrepareInteractiveRebaseCommand`
but not in `runSkipEditorCommand`.
Before this change, some commands such as `SquashAllAboveFixupCommits`
would not work when a different sequence editor, e.g.
[git-interactive-rebase-tool](https://github.com/MitMaro/git-interactive-rebase-tool)
is configured.