Commit graph

2658 commits

Author SHA1 Message Date
Stefan Haller
13c21365c0 Store fromHash/toHash in Pipe struct as pointers
Now that commit hashes are stored in a pool and referenced by pointer by the
commits, we can use those same pointers in the pipes.
2025-04-29 14:57:15 +02:00
Stefan Haller
0f1f455edb Make Commit.Parents a getter for an unexported parents field
This is exactly the same as what we did for Hash earlier. And for the same
reason: we want to turn the parents field into a slice of pointers.
2025-04-29 14:57:15 +02:00
Stefan Haller
e27bc15bbd Store Commit.Hash by pointer (kept in a pool of hashes)
This in itself is not an improvement, because hashes are unique (they are shared
between real commits and rebase todos, but there are so few of those that it
doesn't matter). However, it becomes an improvement once we also store parent
hashes in the same pool; but the real motivation for this change is to also
reuse the hash pointers in Pipe objects later in the branch. This will be a big
win because in a merge-heavy git repo there are many more Pipe instances than
commits.
2025-04-29 14:57:15 +02:00
Stefan Haller
1037371a44 Make Commit.Hash a getter for an unexported hash field
This is in preparation for turning the hash into pointer to a string.
2025-04-29 14:57:15 +02:00
Stefan Haller
97aa7a04e6 Rewrite generateCommits to avoid write access to commit.Parents
We want to unexport Parents in a later commit.
2025-04-29 14:57:15 +02:00
Stefan Haller
5844ec6eb2 Cleanup: use IsMerge instead of counting Parents 2025-04-29 14:57:15 +02:00
Stefan Haller
cb0c8f39bf Simplify code and fix comment
The "// merge commit" comment was plain wrong, this is any commit that has a
parent, merge or not. The "else if" condition was unnecessary, a plain "else"
would have been enough. But the code in the two blocks was almost identical, so
extract the one thing that was different and unify it.

And while we're at it, use IsFirstCommit() instead of counting parents.
2025-04-29 14:57:15 +02:00
Stefan Haller
9d202cf9ea Remove unused function 2025-04-29 14:57:15 +02:00
Stefan Haller
4cfa6e0c98 Modernize benchmarks
See https://go.dev/blog/testing-b-loop
2025-04-29 14:57:15 +02:00
dawe
80e2e76f60 fix wording of random tip
remove a superfluous word
2025-04-29 14:13:55 +02:00
Stefan Haller
159bbb0825 Strip the '+' and '-' characters when copying parts of a diff to the clipboard
This makes it easier to copy diff hunks and paste them into code. We only strip
the prefixes if the copied lines are either all '+' or all '-' (possibly
including context lines), otherwise we keep them. We also keep them when parts
of a hunk header is included in the selection; this is useful for copying a diff
hunk and pasting it into a github comment, for example.

A not-quite-correct edge case is when you select the '--- a/file.txt' line of a
diff header on its own; in this case we copy it as '-- a/file.txt' (same for the
'+++' line). This is probably uncommon enough that it's not worth fixing (it's
not trivial to fix because we don't know that we're in a header).
2025-04-29 11:33:47 +02:00
Stefan Haller
6402c830d5 Remove space after rebase todo
This is very old; I can only guess that this was added at a time where today's
list column handling wasn't in place yet, so the space was needed to separate
columns. This now causes a gap of two spaces between the rebase todo column and
the author column, which I'm sure wasn't intended. Funny that I never noticed.
2025-04-29 11:30:37 +02:00
Stefan Haller
0496e3af50 Disallow creating custom patches when the diff context size is 0
This is very similar to what we are doing for staging or discarding hunks in the
Files panel. Git doesn't allow applying patches with a zero context size (unless
you use the --unidiff-zero option, which is discouraged).
2025-04-29 10:21:18 +02:00
Stefan Haller
da24deb881 Allow changing diff context size and rename threshold when main view is focused 2025-04-23 08:38:46 +02:00
Stefan Haller
30868eead8 Add new command "Move commits to new branch" 2025-04-21 18:12:50 +02:00
Stefan Haller
4bf11eae4b Add free-standing function IsWorkingTreeDirty
The long story: I want to call this function from RefsHelper; however, I can't
make WorkingTreeHelper a field of RefsHelper because RefsHelper is already a
field in WorkingTreeHelper, so that would be a circular dependency.

The shorter story: there's really little reason to have to instantiate a helper
object in order to call a simple function like this. Long term I would like to
get to a state where a lot more of these helper functions are free-standing, and
you pass in the data they need.

While at it, simplify the implementation of AnyStagedFiles and AnyTrackedFiles
to one-liners.
2025-04-21 18:12:50 +02:00
Stefan Haller
9d88d6a44e Remove MergeAndRebaseHelper's dependency on RefsHelper
We want to make MergeAndRebaseHelper a dependency of RefsHelper instead.
2025-04-21 18:12:50 +02:00
Stefan Haller
483195110a Use Model().Branches[0] instead of refsHelper.GetCheckedOutRef() in MergeAndRebaseHelper
It's the same, really, except that GetCheckedOutRef() does a check if any
branches exist and returns nil if not. Since we are accessing the returned
branch unconditionally without checking for nil, it seems this check is not
needed here. (The functions we are touching here are called from handlers that
are guarded with itemSelected or singleItemSelected, so we know that at least
one branch exists.)

The goal is to get rid of the dependency to refsHelper.
2025-04-21 18:12:50 +02:00
Stefan Haller
ecc70f4764 Cleanup: remove unnecessary indirection 2025-04-21 18:12:50 +02:00
Stefan Haller
eaaa937315 Add config for auto-forwarding branches after fetching 2025-04-21 18:06:09 +02:00
Stefan Haller
2174762315 Inline fetchAux into call site
It's only called from this one place, and the call is a one-liner, so it makes
more sense to inline the code there.
2025-04-21 18:06:09 +02:00
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
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
7b17f33e9e Add navigation keybindings to focused main view 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
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
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
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
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
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
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
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