So far, lines in the view corresponded 1:1 to lines in the patch. Once we turn
on wrapping for the staging view (which we don't do yet), this is no longer
true, so we need to convert from view lines to patch lines or vice versa all
over the place.
This doesn't improve the code much in the current state, but we'll add some more
code to this helper function in the next commit, which makes it worth it.
We haven't needed this before since we were only using the function for text in
confirmations and menus, which is unlikely to contain tabs. We are going to use
it for patches in the staging view though, which often do.
to make it more generally usable by clients other than ConfirmationHelper, which
we will do later in this branch. Rename it to WrapViewLinesToWidth while we're
at it.
Add tests; in particular, add a sanity check that we wrap lines the same way as
gocui does. The tests that are added here are the same ones as in gocui for its
lineWrap function, but we'll extend them a bit in later commits in this branch.
This is also what we do in the staging controller, and it makes it so that when
you exit the patch building view and then enter it again (for another file, or
the same one) we select the first hunk again.
- **PR Description**
When moving the first commit of the second branch in a stack down by one
(across the branch head of the first branch), the current behavior is
broken: we move the commit only past the update-ref todo of branch1,
which means the order of commits stays the same and only the branch head
icon moves up by one. However, we move the selection down by one, so the
wrong commit is selected now. This is especially bad if you type a bunch
of ctrl-j quickly in a row, because now you are moving the wrong commit.
There would be two possible ways to fix this:
1) keep the moving behavior the same, but don't change the selection
2) change the behavior so that we move the commit not only past the
update-ref, but also past the next real commit.
You could argue that 1) is the more desirable fix, as it gives you more
control over where exactly the moved commit goes; however, it is much
trickier to implement, so we go with 2) for now. If users need more
fine-grained control, they can always enter an interactive rebase first.
While we're at it, also fix moving a commit across an exec todo in an
interactive rebase, which is currently broken (it moves the commit one
too far).
Fixes#4040.
- **Please check if the PR fulfills these requirements**
* [x] Cheatsheets are up-to-date (run `go generate ./...`)
* [x] Code has been formatted (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
* [x] Tests have been added/updated (see
[here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md)
for the integration test guide)
* [ ] Text is internationalised (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
* [ ] If a new UserConfig entry was added, make sure it can be
hot-reloaded (see
[here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig))
* [ ] Docs have been updated if necessary
* [x] You've read through your own file changes for silly mistakes etc
The test demonstrates that the behavior is undesirable right now: we move the
commit only past the update-ref todo of branch1, which means the order of
commits stays the same and only the branch head icon moves up by one. However,
we move the selection down by one, so the wrong commit is selected now. This is
especially bad if you type a bunch of ctrl-j quickly in a row, because now you
are moving the wrong commit.
There are two possible ways to fix this:
1) keep the moving behavior the same, but don't change the selection
2) change the behavior so that we move the commit not only past the update-ref,
but also past the next real commit.
You could argue that 1) is the more desirable fix, as it gives you more control
over where exactly the moved commit goes; however, it is much trickier to
implement, so we go with 2) for now (and that's what the commented-out
"EXPECTED" section documents here). If users need more fine-grained control,
they can always enter an interactive rebase first.
For non-merge commits we change "pick" to "drop" when we delete them. We do this
so that we can use the same code for dropping a commit no matter whether we are
in an interactive rebase or not. (If we aren't, we could just as well delete the
pick line from the todo list instead of setting it to "drop", but if we are, it
is better to keep the line around so that the user can change it back to "pick"
if they change their mind.)
However, merge commits can't be changed to "drop", so we have to delete them
from the todo file. We add a new daemon instruction that does this.
We still don't allow deleting a merge commit from within an interactive rebase.
The reason is that we don't show the "label" and "reset" todos in lazygit, so
deleting a merge commit would leave the commits from the branch that is being
merged in the list as "pick" commits, with no indication that they are going to
be dropped because they are on a different branch, and the merge commit that
would have brought them in is gone. This could be very confusing.
One of the comments we are deleting here said:
// Comparing just the hash is not enough; we need to compare both the
// action and the hash, as the hash could appear multiple times (e.g. in a
// pick and later in a merge).
I don't remember what I was thinking when I wrote this code, but it's nonsense
of course. Maybe I was thinking that the hash that appears in a "merge" todo
would be the hash of the commit that is being merged in (which would then
actually appear in an earlier pick), but it isn't, it's the hash of the merge
commit itself (so that the rebase can reuse its commit message). Which means
that hashes are unique, no need to compare the action.
So far it didn't have to handle the case where one hash is empty and the other
isn't, but in the next commit we need that, so let's handle that case correctly.
There's enough logic in the function now that it's worth covering it with tests.
Not much of a change in behavior, because moving merge commits was already not
possible. However, it failed with a cryptic error message ("Todo fa1afe1 not
found in git-rebase-todo"), so disable it properly instead.
When enabled, it adds "+n -m" after each file in the Files panel to show how
many lines were added and deleted, as with `git diff --numstat` on the command
line.
- **PR Description**
This PR fixes to issues with the current implementation of the OSConfig
for WSL:
**File explorer**
When using the file explorer from WSL, for instance by pressing "o" in
the "Files" menu, the explorer always opens on the default landing page.
This is caused by the filepath being expressed in WSL format instead of
the expected Windows format. For instance:
- "/home/myuser/path/to/my/file" should be
"\\wsl$\MyDistroName\home\myuser\path\to\my\file"
- "/mnt/c/path/to/my/file" should be "C:\path\to\my\file"
There's a utility to do that in WSL, `wslpath`. We use it in the Open to
format the filename before passing it to the Powershell command
**Link URLs**
Opening links containing ampersands inside lazygit (a pull-request
creation page in BitBucket Server, for instance) returns the following
Powershell error:
> The ampersand (&) character is not allowed. The & operator is reserved
> for future use; wrap an ampersand in double quotation marks ("&") to
> pass it as part of a string.
We fix it by enclosing the URL in single quotes.
**Notes on this PR**
This is my first PR on this repo, please tell me if something is needed.
I read the contributing guide.
The OS-specific logic doesn't appear to be tested in integration and
unit tests, so I didn't add tests.
- **Please check if the PR fulfills these requirements**
* [x] Cheatsheets are up-to-date (run `go generate ./...`)
* [x] Code has been formatted (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
* [ ] Tests have been added/updated (see
[here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md)
for the integration test guide)
* [ ] Text is internationalised (see
[here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
* [ ] If a new UserConfig entry was added, make sure it can be
hot-reloaded (see
[here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig))
* [ ] Docs have been updated if necessary
* [x] You've read through your own file changes for silly mistakes etc
Opening links containing ampersands inside lazygit (a pull-request
creation page in BitBucket Server, for instance) returns the following
Powershell error:
> The ampersand (&) character is not allowed. The & operator is reserved
> for future use; wrap an ampersand in double quotation marks ("&") to
> pass it as part of a string.
We fix it by enclosing the URL in single quotes.
The OS command to open file in explorer in WSL doesn't currently work as
expected; it always opens the file explorer at the default opening
location. This is because the {{filename}} variable returns the path in
WSL format, and not in the format expected by Windows.
We use wslpath, a utility shipped with WSL, to make the path conversion.
It is needed by both call sites of this function. This has the added benefit
that the argument doesn't unnecessarily show up in the status view when diffing
mode is on.
In 67b8ef449c we changed the "edit" command to insert a "break" after the
selected commit, rather than setting the selected todo to "edit". The reason for
doing this was that it now works for merge commits too.
Back then, I claimed "In most cases the behavior is exactly the same as before."
Unfortunately that's not true, there are two reasons why the previous behavior
was better (both are demonstrated by tests earlier in this branch):
- when editing the last commit of a branch in the middle of a stack of branches,
we are now missing the update-ref todo after it, which means that amending the
commit breaks the stack
- it breaks auto-amending (see the added test earlier in this branch for an
explanation)
For these reasons, we are going back to the previous approach of setting the
selected commit to "edit" whenever possible, i.e. unless it's a merge commit.
The only scenario where this could still be a problem is when you have a stack
of branches, and the last commit of one of the branches in the stack is a merge
commit, and you try to edit that. In my experience with stacked branches this is
very unlikely, in almost all cases my stacked branches are linear.
We will need this because under some conditions we are going to use this
function to edit a range of commits, and we can't set merge commits to "edit".
This corresponds to the code in startInteractiveRebaseWithEdit which has similar
logic.
It is a bit unfortunate that we will have these two different ways of setting
todos to edit: startInteractiveRebaseWithEdit does it after stopping in the
rebase, in the Then function of its refresh, but InteractiveRebase does it in
the daemon with a ChangeTodoActionsInstruction. It still makes sense though,
given how InteractiveRebase works.
This not only affects "edit", but also "drop", "fixup", and "squash".
Previously, when trying to use these for a range selection that includes a merge
commit, they would fail with the cryptic error message "Some todos not found in
git-rebase-todo"; now they simply exclude the merge commit. I'm not sure if one
is better or worse than the other, and we should probably simply disable the
commands when a merge commit is selected, but that's out of scope in this PR.
This is very similar to edit_range_select_outside_rebase.go, except that it
selects commits right after, and including, a merge commit.
This test already works correctly. The reason we add it is that we are going to
have two different implementations of the `e` command depending on whether the
last selected commit is a merge commit, and we want to make sure they both work
with a range selection.
Auto-amending is a little-known feature of git that is very convenient once you
know it: whenever you stop at a commit marked with `edit` in an interactive
rebase, you can make changes and stage them, and when you continue the rebase
they automatically get amended to the commit you had stopped at. This is so
convenient because making changes to a commit is one of the main reasons why you
edit a commit.
Unfortunately this currently doesn't work in lazygit because we don't actually
use `edit` to stop at the first commit (instead, we add a `break` todo after it,
which doesn't have the auto-amend functionality).
We'll improve this later in this branch.
- **PR Description**
This allows range-selecting multiple branches and deleting them all at
once. We allow deleting remote branches (or local and remote branches)
as long as *all* selected branches have one.
We show the warning about force-deleting as soon as at least one of the
selected branches is not fully merged.
We allow deleting remote branches (or local and remote branches) only if *all*
selected branches have one.
We show the a warning about force-deleting as soon as at least one of the
selected branches is not fully merged.
The added test only tests a few of the most interesting cases; I didn't try to
cover the whole space of possible combinations, that would have been too much.
Since we want to select multiselections, this will make it easier to pass a
slice of remote branches. It does require that for the case of the local
branches panel we need to synthesize a RemoteBranch object from the selected
local branch, but that's not hard.