The true issue was that we were focusing the line in the view before it gets resized in the layout function.
This meant if the view was squashed in accordion mode, the view wouldn't know how to set the cursor/origin to
focus the line.
Now we've got a queue of 'after layout' functions i.e. functions to call at the end of the layout function,
right before views are drawn.
The only caveat is that we can't have an infinite buffer so we're arbitrarily capping it at 1000 and dropping
functions if we exceed that limit. But that really should never happen.
This happens consistently for my when I close my MacBook's lid. It seems that
MacOS locks the user's keychain in this case, and since I have my keychain
provide the pass phrases for my ssh keys, fetching fails because it tries to
prompt me for a pass phrase.
This all worked correctly already, we have the FailOnCredentialRequest()
mechanism specifically for this situation, so all is great. The only problem was
that it was trying to pause the ongoing task while prompting the user for input;
but the task is nil for a background fetch (and should be).
It said "Press tab to toggle focus", which is wrong for people who remapped
their togglePanel key binding to something else. Print the actual key binding
instead.
As discussed in https://github.com/jesseduffield/lazygit/pull/2599, it
makes more sense to have the user specify whether they want verbose
commits from their own git config, rather than lazygit config.
This means that we can remove all the code (including test coverage)
associated with the custom verbose flag, and lazygit will just inherit
the .gitconfig settings automatically.
We have a use-case to rebind 'm' to the merge action in the branches panel. There's three ways to handle this:
1) For all global keybindings, define a per-panel key that invokes it
2) Give a name to all controller actions and allow them to be invoked in custom commands
3) Allow checking for merge conflicts after running a custom command so that users can add their own 'git merge' custom command
that matches the in-built action
Option 1 is hairy, Option 2 though good for users introduces new backwards compatibility issues that I don't want to do
right now, and option 3 is trivially easy to implement so that's what I'm doing.
I've put this under an 'after' key so that we can add more things later. I'm imagining other things like being able to
move the cursor to a newly added item etc.
I considered always running this hook by default but I'd rather not: it's matching on the output text and I'd rather something
like that be explicitly opted-into to avoid cases where we erroneously believe that there are conflicts.
It seems that older git versions would drop empty commits when rebasing. Since
this aspect is not relevant to what we're testing here, fix this by simply
avoiding empty commits in these tests.
The test apply_in_reverse_with_conflict.go fails in git versions 2.30.8 and
earlier. Apparently the output "Applied patch to 'file2' cleanly" was only added
more recently. It's not essential that we check this output.
Save has been deprecated for a while, push is the recommended way to save a
stash. Push has been available since 2.13, so we can use it without problems.
Older versions of git don't support the -b option yet. However, no version of
git complains about the -c option, even when the init.defaultBranch config is
not supported.
For older git versions we won't be able to support any other main branch than
"master", so hard-code that in Init.
This doesn't fix anything for older versions yet; see the next commit for that.
Now that we are running each test 6 times on CI, the risk of flakiness
is higher. I want to fix these tests for good but it'l take time, so
we're just retrying for now
The code in getHydratedRebasingCommits relied on the assumption that the
git-rebase-todo file contains full SHAs. This has only been true from 2.25.2 on,
before that it would contain abbreviated SHAs. Fix this by storing fullCommits
in a slice instead of a map, and using a linear search.
I don't know why we're getting index.lock errors but they're impossile to stop
anyway given that other processes can be calling git commands. So we're retrying
a few times before re-raising. To do this we need to clone the command and the current
implementation for that is best-effort.
I do worry about the maintainability of that but we'll see how it goes.
Also, I thought you'd need to clone the task (if it exists) but now I think not;
as long as you don't call done twice on it you should be fine, and you shouldn't
be done'ing a task as part of running a command: that should happen higher up.
It's not clear what was happening but it seemed like we sometimes weren't
fully writing to our stdout buffer (which is used for the error message)
even though we had returned from cmd.Wait().
Not sure what the cause was but removing an unnecessary goroutine fixed it.
I've simplifiied the code because it was too complex for the current requirements, and this fixed the misc/initial_open
test which was occasionally failing due to a race condition around busy tasks
The global counter approach is easy to understand but it's brittle and depends on implicit behaviour that is not very discoverable.
With a global counter, if any goroutine accidentally decrements the counter twice, we'll think lazygit is idle when it's actually busy.
Likewise if a goroutine accidentally increments the counter twice we'll think lazygit is busy when it's actually idle.
With the new approach we have a map of tasks where each task can either be busy or not. We create a new task and add it to the map
when we spawn a worker goroutine (among other things) and we remove it once the task is done.
The task can also be paused and continued for situations where we switch back and forth between running a program and asking for user
input.
In order for this to work with `git push` (and other commands that require credentials) we need to obtain the task from gocui when
we create the worker goroutine, and then pass it along to the commands package to pause/continue the task as required. This is
MUCH more discoverable than the old approach which just decremented and incremented the global counter from within the commands package,
but it's at the cost of expanding some function signatures (arguably a good thing).
Likewise, whenever you want to call WithWaitingStatus or WithLoaderPanel the callback will now have access to the task for pausing/
continuing. We only need to actually make use of this functionality in a couple of places so it's a high price to pay, but I don't
know if I want to introduce a WithWaitingStatusTask and WithLoaderPanelTask function (open to suggestions).
We had some test flakiness involving the index.lock file which is fixed by this commit.
We shouldn't be accessing newTaskID without the mutex, although I'm surprised that this
actually fixes the issue. Surely we don't have tasks (which typically render to the main
view) which use index.lock?
We had a race condition due to refreshing branches in two different places, one which refreshed reflog commits
beforehand. The race condition meant that upon load we wouldn't see recency values (provided by the reflog commits)
against the branches
I want to see how we go removing all retry logic within a test. Lazygit should be trusted to tell us when it's no longer busy,
and if it that proves false we should fix the issue in the code rather than being lenient in the tests
Turns out we're just running our refresh functions one after the other which isn't ideal but we can fix that separately.
As it stands this wait group isn't doing anything.
I don't know if this is a hack or not: we run a git command and increment the pending action
count to 1 but at some point the command requests a username or password, so we need to prompt
the user to enter that. At that point we don't want to say that there is a pending action,
so we decrement the action count before prompting the user and then re-increment it again afterward.
Given that we panic when the counter goes below zero, it's important that it's not zero
when we run the git command (should be impossible anyway).
I toyed with a different approach using channels and a long-running goroutine that
handles all commands that request credentials but it feels over-engineered compared to this
commit's approach.
The remote branches controller was using its own escape method meaning it didn't go through the flow of cancelling
an active filter. It's now using the same approach as the sub-commits and commit-files contexts: defining a parent
context to return to upon hittin escape.
Given that we now persist search/filter states even after a side context loses focus, we need to make it really
clear to the user that the context is currently being searched/filtered
This is a pickle: initially I wanted it so that a filter would cancel automatically if the current context lost focus.
But there are situations where you want to retain the focus, e.g. when a popup appears, or when you view the commits
of a branch. The issue is that when you view the commits of a branch, the branches context is removed from the context
stack. Even if this were not the case, you could imagine going branches -> sub-commits -> files -> sub-commits, where
in that case branches would definitely be off the stack upon navigating to the files context.
So because I'm too lazy to find a proper solution to this problem, I'm just making it so that filters in side contexts
are retained unless explicitly cancelled.
There's another edge case this commit handles which is that if I'm in the sub-commits context via the branches context
and start a search, then navigate to the reflog context and hit enter to get to the sub-commits context again, I need
to cancel the search before I switch. Likewise with the commit files context.