Commit graph

6406 commits

Author SHA1 Message Date
Stefan Haller
3577808a14 Remove double Refresh
fetchAux already calls Refresh (and with a more targeted scope too), no need to
call it again here.
2025-04-21 18:06:09 +02:00
Stefan Haller
e4362eea60
Focus the main view (#4429)
- **PR Description**

This adds a new `0` keybinding to the side panels that focuses whatever
main view is currently displayed, with the goal of making it easier to
scroll the main view (using the normal navigation keys `,` `.` `<` `>`),
and being able to search the main view using `/`.

Alternatively to pressing `0` you can also click the main view to focus
it. Note that previously it was possible to go directly to the staging
panel by clicking in the main view when a file was selected; this now
takes a double click, because the first click just focuses the main
view, but you can go to staging from there by clicking again.

I'm reasonably happy with the overall behavior, but it takes some
getting used to, so we'll want to test this for a while to see if it
doesn't make the focus handling too confusing.

Fixes #3988.
2025-04-21 18:05:38 +02:00
Stefan Haller
4e21a096b9 Re-render focused main view on refresh if needed 2025-04-21 18:03:24 +02:00
Stefan Haller
98e4cb733f Allow clicking in the respective other main view to switch focus to it 2025-04-21 18:03:24 +02:00
Stefan Haller
fbb8b2e17e Allow clicking in focused main view to go to staging
Only works if a file is selected.
2025-04-21 18:03:24 +02:00
Stefan Haller
acfa024915 Allow clicking in main view to focus it 2025-04-21 18:03:24 +02:00
Stefan Haller
338064ac2c Read all lines from task when starting to search 2025-04-21 18:03:24 +02:00
Stefan Haller
ec51efc82c Make the main view searchable 2025-04-21 18:03:24 +02:00
Stefan Haller
2b399a3c36 Read all lines from task when jumping to bottom 2025-04-21 18:03:19 +02:00
Stefan Haller
60887eddd0 Use readLines channel only for command tasks
And only while the task is running.

This avoids accumulating lots of blocked goroutines when scrolling a view down
more than 1024 times (the capacity of the readLines channel).
2025-04-21 18:03:19 +02:00
Stefan Haller
7b17f33e9e Add navigation keybindings to focused main view 2025-04-21 18:03:19 +02:00
Stefan Haller
fa35f661d9 Update keybindings, config docs, and schema 2025-04-21 18:03:19 +02:00
Stefan Haller
1a93b2324b Allow focussing the main view
In this commit this is only possible by pressing '0' in a side panel; we'll add
mouse clicking later in the branch.

Also, you can't really do anything in the focused view except press escape to
leave it again. We'll add some more functionality in a following commit.
2025-04-21 18:03:19 +02:00
Stefan Haller
b7b7c65999 Add class MainContext
In this state of the code it isn't worth much because it's not any more than a
SimpleContext, but we'll add things to it later in the branch.
2025-04-21 18:03:18 +02:00
Stefan Haller
2a2705dcc3 Always render diffs to the main/secondary context pair, even for files
Previously we would render the diff for a directory to the main/secondary pair,
but a diff for a file to the staging/stagingSecondary pair. (And similar for
commit files: main/secondary for directories, but
patchBuilding/patchBuildingSecondary for files.)

I always found this confusing and couldn't really understand why we are doing
this; but now it gets in my way because I want to attach a controller to
main/secondary so that they can be focused. So change it to always use the main
context pair for everything we render from a side panel.
2025-04-21 18:03:18 +02:00
Stefan Haller
7b96615792 Add IGuiCommon.GetViewBufferManagerForView
So that we don't have to pass the map to controllers.
2025-04-21 18:03:18 +02:00
Stefan Haller
b97dd6bc3f Remove utils.Clamp, use lo.Clamp instead 2025-04-21 18:03:18 +02:00
Stefan Haller
6c0ee7df2b Bump gocui 2025-04-21 18:03:11 +02:00
Stefan Haller
548d486aee
Section headers for rebase todos and actual commits (#4463)
- **PR Description**

During interactive rebase, or when stopping with conflicts in a
cherry-pick or revert, show section headers for the todo items and the
actual commits. This makes it much clearer where the current head commit
is. Get rid of the "<-- YOU ARE HERE" marker that we would previously
show; it is no longer needed. (We still show the "<-- CONFLICT" marker
though.)

For example:
```
╭─[4]─Commits - Reflog───────────────────────────╮
│--- Pending rebase todos ---                    │
│6562f903 pick  CI commit 03                     │
│--- Commits ---                                 │
│56a04448       CI ◯ commit 02                   │
│6d0c0e41       CI ◯ commit 01                   │
```
2025-04-20 16:09:40 +02:00
Stefan Haller
74054c9d70 Remove the "YOU ARE HERE" marker
Now that we have sections, it is no longer needed.

Keep the "<-- CONFLICTS" marker though.
2025-04-20 16:06:15 +02:00
Stefan Haller
6cbc1e0ace Add section headers for rebase todos, cherry-picks, reverts, and actual commits 2025-04-20 16:06:15 +02:00
Stefan Haller
98c19feccf Add new commit status StatusCherryPickingOrReverting
This is needed because we want to show different section headers for rebase
todos and cherry-pick/revert todos.
2025-04-20 16:06:15 +02:00
Stefan Haller
e90a3dc666 Fix view selection running out of sync with list selection when view isn't focused
When rerendering a view at the end of a refresh, we call HandleFocus only if the
view has the focus. This is so that we rerender the main view for the new
selection.

What was missing here is to update the view selection from the list selection if
the view doesn't have the focus, so that the selection is painted properly.
Normally this is not relevant because you don't see the selection if another
side panel has the focus; however, you do see it as an inactive selection when
e.g. a popup is shown, in which case it does matter.

This will become more important when we introduce section headers for commits,
because in that case the view selection needs to change when the working copy
state changes from normal to rebasing or vice versa, even if the list selection
stays the same.

The changed test submodule/reset.go shows how this was wrong before: when
entering the submodule again after resetting, there is a refresh which keeps the
same branch selected as before (master); however, since the branches panel is
not focused, the view didn't notice and kept thinking that the detached head is
selected (which it isn't, you can tell by running the test in sandbox mode and
focusing the branches panel at the end: you'll see that master is selected). So
the change in this commit fixes that.
2025-04-20 16:06:15 +02:00
Stefan Haller
0dab37a631
Allow reverting a range of commits (#4444)
- **PR Description**

This is part four of a four part series of PRs that improve the
cherry-pick and revert experience.

With this PR we support reverting a range selection of commits.

Fixes #3272
2025-04-20 16:05:27 +02:00
Stefan Haller
945b023eb5 Support range selection for reverting commits 2025-04-20 16:03:06 +02:00
Stefan Haller
1c91999f61 Inline afterRevertCommit
It's only called from one place now, so there's no reason not to inline it.
2025-04-20 16:03:06 +02:00
Stefan Haller
f14a3cdd46 Remove the "Select parent commit" prompt when reverting a merge commit
In pretty much 100% of the cases, you want to use -m1, so spare users the
complexity of a confusing prompt.

See
https://public-inbox.org/git/e60a8b1a-98c8-4ac7-b966-ff9635bb781d@haller-berlin.de/
for some discussion.
2025-04-20 16:03:06 +02:00
Stefan Haller
c13c6356e3
Use "git cherry-pick" for implementing copy/paste of commits (#4443)
- **PR Description**

This is part three of a four part series of PRs that improve the
cherry-pick and revert experience.

With this PR we reimplement copy/paste of commits to use `git
cherry-pick` under the hood. We do this because
- it's closer to what you would do on the command line
- it simplifies the code a bit
- it allows us to support cherry-picking merge commits.

Fixes #1374
Fixes #3317
2025-04-20 16:02:51 +02:00
Stefan Haller
108054efc6 Allow cherry-picking merge commits
Now that we use git cherry-pick to implement it, there's no reason not to.
2025-04-20 15:59:48 +02:00
Stefan Haller
27825eba9e Remove unused cherry-picking code in daemon 2025-04-20 15:59:48 +02:00
Stefan Haller
4b35434eba Use "git cherry-pick" for implementing copy/paste of commits
We do this because
- it's closer to what you would do on the command line
- it simplifies the code a bit
- it will allow us to support cherry-picking merge commits.
2025-04-20 15:59:48 +02:00
Stefan Haller
05b3ae9524 Reference original commits in CherryPicking mode instead of synthesizing new ones
Previously we would create new Commit objects to store in the CherryPicking mode
which only contained a name and hash, all other fields were unset. I'm not sure
why we did this; it's easier to just reference the original commits. Later on
this branch we will need this because we need to determine whether a copied
commit was a merge commit (by looking at its Parents field).
2025-04-20 15:59:48 +02:00
Stefan Haller
b7d01d67a6
Show todo items for pending cherry-picks and reverts (#4442)
- **PR Description**

This is part two of a four part series of PRs that improve the
cherry-pick and revert experience.

With this PR we include pending cherry-picks and reverts in the commit
list (like rebase todos) when a cherry-pick or revert stops with
conflicts; also, we show the conflicting item in the list like we do
with conflicting rebase todos.

As with the previous PR, this is not really very useful yet because you
can't revert a range of commits, and we don't use git cherry-pick for
copy/paste. Both of these will change in later PRs in this series, so
again this is preparation for that.
2025-04-20 15:58:54 +02:00
Stefan Haller
b350876f84 Disallow any changes to commits or todos when cherry-picking or reverting
We treat the .git/sequencer/todo file as read-only. Technically it seems it
would be possible to treat it as modifiable in the same way as
.git/rebase-merge/git-rebase-todo, effectively turning a cherry-pick or revert
that stops at a conflict into an interactive rebase; however, git itself doesn't
allow this (there is no "git cherry-pick --edit-todo"), so it seems safer not to
rely on it.

Theoretically it would be possible to allow modifying the rebase todos when a
cherry-pick or revert conflicts in the middle of a rebase. However, it would
introduce a bit of complexity to support this, as we would have to be able to
distinguish between rebasing todos and cherry-picking/reverting todos, which we
currently can't; it could also be a bit error-prone as far as edge cases are
concerned. And it's really a pretty uncommon situation, so it doesn't seem worth
it, and we just forbid all modifications to todos whenever we are cherry-picking
or reverting.
2025-04-20 15:55:44 +02:00
Stefan Haller
5ba8d42c80 Fix the bug described in the previous commit
What happens here is that when stopping on an "edit" todo entry, we rely on the
assumption that if the .git/rebase-merge/amend file exists, the command was
successful, and if it doesn't, there was a conflict. The problem is that when
you stop on an edit command, and then run a multi-commit cherry-pick or rebase,
this will delete the amend file. You may or may not consider this a bug in git;
to work around it, we also check the existence of the rebase-merge/message file,
which will be deleted as well by the cherry-pick or revert.
2025-04-20 15:55:44 +02:00
Stefan Haller
9b88052a4e Add test demonstrating problem with revert (or cherry-pick) during a rebase
This problem can't happen inside of lazygit itself right now, but this will
change in the future. It will only happen when you stopped in an interactive
rebase on an "edit" entry, and then you perform a revert or cherry-pick
consisting of more than one commit; in this situation lazygit will show a
conflict although there is none.

This is not possible with lazygit yet, as we don't support range-select for
reverting, and we don't use `git cherry-pick` for cherry-picking. Both will
change in the future, so it's good to fix this bug.
2025-04-20 15:55:44 +02:00
Stefan Haller
6b6d881624 Add test to check that an "edit" entry correctly shows a conflict
This works correctly, we are only adding this as a regression test to verify
that the change later in this branch doesn't break it.
2025-04-20 15:55:44 +02:00
Stefan Haller
bb4d03db1f Show todos (and conflicting commit) for cherry-pick and revert 2025-04-20 15:55:44 +02:00
Stefan Haller
687bae48ed Simplify the MergeRebasingCommits call in GetCommits (slightly)
MergeRebasingCommits already merges the rebasing commits into the commits slice
that is passed in, so it doesn't make sense to append the result to commits
again. It isn't a problem, but only because commits is always empty.
2025-04-20 15:55:44 +02:00
Stefan Haller
ff465e2581 Show original todo action instead of "conflict", and show <-- CONFLICT instead
It is useful to see if the conflicted commit was a "pick" or an "edit". What's
more, we're about to add support for showing cherry-picks and reverts, and
seeing that a conflicted commit was a revert is important because its diff is
backwards compared to the diff of the conflicting files in the Files panel.
2025-04-20 15:55:44 +02:00
Stefan Haller
9c8f987934 Use commit.IsTODO instead of comparing Status against models.StatusRebasing
This is equivalent in the current state of the code, but it will no longer be
after the next commit, because we will introduce a new status value
StatusConflicted. And in a later PR we might add yet another value
StatusCherryPicking to distinguish rebase todos from cherry-pick todos; using
commit.IsTODO is a safer way to check whether a commit is any of these.
2025-04-20 15:55:44 +02:00
Stefan Haller
d84ee606e8 Remove unused enum entry StatusSelected 2025-04-20 15:55:44 +02:00
Stefan Haller
3dc045b69c
Continue/abort a conflicted cherry-pick or revert (#4441)
- **PR Description**

This is part one of a four part series of PRs that improve the
cherry-pick and revert experience.

With this first PR we make it possible to continue or abort a
cherry-pick or revert operation, in the same way you can continue or
abort a rebase or merge. Currently this is only relevant for revert,
because lazygit doesn't use git cherry-pick for copying/pasting commits.
This will change in a later PR in this series though, so here we are
already preparing for that.

Fixes #1807
2025-04-20 15:55:11 +02:00
Stefan Haller
90db796f42 Add DisabledReason for rebase options when not rebasing or merging 2025-04-20 15:53:17 +02:00
Stefan Haller
3e5024480d Check for conflicts after reverting a commit
This way we get the usual menu for viewing the conflicts or aborting, like for
rebases.
2025-04-20 15:53:17 +02:00
Stefan Haller
4b3262ab3e Add test for reverting a commit that conflicts
This works already (except that the "you are here" marker is not right yet, but
that's an issue for another PR), just add a test that verifies it.
2025-04-20 15:53:17 +02:00
Stefan Haller
362678e2ef Mention which command is continued in PromptToContinueRebase
When you are in the middle of a rebase, and you cherry-pick a commit which
conflicts, it helps to be clear on whether you are prompted to continue the
cherry-pick or the rebase.
2025-04-20 15:53:17 +02:00
Stefan Haller
542525743c Make WorkingTreeState a struct, and add cherry-picking and reverting states 2025-04-20 15:53:17 +02:00
Stefan Haller
8af8f7754b Move types/enums/enums.go to working_tree_state.go
It looks like enums.go was supposed to be file that collects a bunch of enums,
but actually there's only one in there, and since it has methods, it deserves to
be in a file of its own, named after the type.
2025-04-20 15:53:17 +02:00
Stefan Haller
e1eb95b2b3 Add test for a special situation in rebases involving empty commits
The situation is that you perform a rebase, and one of the commits becomes empty
during the rebase, in a way that couldn't be predicted before the rebase
started. To explain: git rebase has some logic where it immediately discards
commits if it can tell that they already exist in the branch being rebased onto;
it does this by looking at the patch ids of the commits to work out which
commits already exist upstream. But for those commits that become empty even
though there isn't a corresponding commit upstream, git stops with an error, and
lazygit detects this (in CheckMergeOrRebaseWithRefreshOptions) and automatically
continues the rebase.

This all works fine; I'm adding this test because I almost broke this during
development of this branch, so I'm adding it to guard against regressions.
2025-04-20 15:53:17 +02:00