Commit Graph
216 Commits
Author SHA1 Message Date
Stefan Haller d181615c31 Make integration tests using commits more robust
Some tests assert that a specific commit subject does or doesn't occur
in the main view; interactive_rebase/outside_rebase_range_select.go is
an example for this, it asserts `t.Views().Main().Content(
DoesNotContain("commit 06"))`. The problem with this kind of assertion
and our test commit naming scheme is that the diff view begins with a
"commit <hash>" line, and when that hash happens to start with "06" the
assertion matched it and failed spuriously. This was usually masked by
our MaxAttempts=2 that we currently use for integration tests (it's
quite unlikely that the commit gets a hash beginning with "06" twice in
a row). However, we want to get to a state where we can set MaxAttempts
to 1, so make this more robust by changing our naming scheme.
2026-07-09 11:56:27 +02:00
Stefan Haller aa46a69f77 Remove unused function ExpectClipboard
This can't be used because it wouldn't work on CI; delete it so that
coding agents aren't tempted to use it.
2026-07-04 13:05:09 +02:00
Stefan HallerandClaude Opus 4.8 ad507d67f4 Only prompt to continue a rebase/merge if we started it
When conflicts of an in-progress rebase/merge/cherry-pick/revert are
resolved, lazygit pops up a prompt offering to continue it. This is
helpful when you started the operation in lazygit and resolved the
conflicts in your editor. But it's confusing when the operation was
started outside lazygit — e.g. by a coding agent in another terminal
that resolves the conflicts but hasn't continued yet because it's still
running tests or fixing the build. lazygit would then prompt unbidden.

Track whether the in-progress operation was started from within lazygit,
and only show the prompt in that case. We record this right after running
a merge/rebase step (in CheckMergeOrRebaseWithRefreshOptions, the
subprocess branch of genericMergeCommand, and the custom-command
conflict path), and clear it whenever a refresh observes that no
operation is in progress — which also handles an operation that was
finished or aborted externally.

The conflict-resolution tests start their operation by running git
directly (not through lazygit's UI), so they call the new test helper
Common.PretendMergeOrRebaseStartedInLazygit to have lazygit treat the
operation as its own and still get the prompt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 18:28:07 +02:00
Stefan HallerandClaude Opus 4.8 2614156b2f Add an IsActiveTab assertion for integration tests
Side panel tabs share a window, so which tab is shown is decided by view
z-order rather than the visibility flag (every tab in a window is
'visible'). Tests had no way to assert which tab is actually drawn in
front, which is distinct from which view has keyboard focus. Expose the
window's top view and add an IsActiveTab assertion built on it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:15:18 +02:00
Stefan HallerandClaude Opus 4.8 30559f1058 Let integration tests post a focus event
Lazygit reloads changed config files when its terminal window regains
focus, but the test harness had no way to simulate that focus event, so
the live config-reload path was untestable. Add a focus event to the
replayed-events queue and expose it through the GuiDriver as FocusIn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:15:18 +02:00
Stefan HallerandClaude Opus 4.7 bb8955f2de Load direnv environment when switching repos
When a user opens a repo from the recent-repos menu or jumps between
worktrees inside lazygit, only the env vars present at process startup
reach subprocesses. That breaks pre-commit hooks and other tools whose
dependencies are pulled in by a per-repo .envrc — users were left with
read-only operations because the env their shell would normally load via
direnv never made it into lazygit's git invocations.

Shell out to `direnv export json` after each chdir and apply the JSON
delta via os.Setenv/Unsetenv. direnv tracks the previous load in its own
DIRENV_DIFF env var, so the delta also unloads vars from the old repo
when entering one without a matching .envrc. If direnv isn't on PATH the
call is a no-op, so users who don't use direnv pay nothing and users who
do need no config to opt in. Any stderr direnv emits (loading messages,
"blocked .envrc" errors, etc.) goes to the command log.

The integration test puts a fake direnv on PATH and asserts that a value
it exports reaches a custom command after switching repos. Wiring this
up needed runner.go to support `{{actualPath}}` placeholders in
ExtraEnvVars, mirroring the existing support for ExtraCmdArgs, so the
test can prepend a fixture-relative directory to PATH.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 09:05:01 +02:00
Stefan Haller 3ecca88bd8 Convert JumpToBlock to a list of multi-key bindings
JumpToBlock is special: each of its 5 elements is the binding for one side
window (status / files / branches / commits / stash), not an alternate for a
single command. Change the field from []string to []Keybinding so each window
slot can have alternates of its own.

The schema becomes "an array of 5 keybindings, each itself a string or array of
strings", which falls out cleanly from how the Keybinding type inlines into the
generated schema. Existing configs (a flat array of 5 strings) keep validating
because each element is unmarshalled through Keybinding's scalar-or-sequence
decoder.
2026-05-25 15:32:47 +02:00
Stefan Haller 5748d82073 Convert keybinding fields to Keybinding
Until now every keybinding config field was a plain string. That meant a user
couldn't ask for two keys to invoke a command — the config silently accepted
only one form.

Convert every string-typed field across all 13 KeybindingXxxConfig structs to
Keybinding so the union type extends to every command. Defaults wrap their
single-key value in Keybinding{...} so the generated Config.md still renders one
scalar key per binding.

The alt fields keep their separate Binding registrations for now: this commit
does not yet introduce the merge mechanism that folds them into the main field —
that comes in a follow-up. Consumers previously calling opts.GetKeys on a string
field now call opts.GetKeys on the Keybinding, or take .String() / Keys[0] where
a single value is needed.

Adds a Keybinding.String helper for rendering, schema-generator work that
inlines the Keybinding union into each consuming property, and a unit test
covering the user-facing scalar/sequence YAML forms for quit.
2026-05-25 15:32:47 +02:00
Stefan Haller 880064b987 Use the isolated test env for shell commands
Shell.RunShellCommand was passing os.Environ() to its child, while its
sibling runCommandWithOutputAndEnv has used the minimal
NewTestEnvironment since late 2023 when env isolation was introduced;
the sh path was just missed.

This matters when integration tests run from inside a `git rebase -x`
exec in a linked worktree: git sets GIT_DIR=<main>/.git/worktrees/<name>
for the exec, and it leaks all the way down through bash, just, go test,
and the test process, into every git invocation RunShellCommand spawns.
cmd.Dir becomes irrelevant — git resolves GIT_DIR over cwd-based
discovery, with the work-tree taken from the gitdir file (i.e. the
worktree root). So `git checkout -b conflict` in a test fixture creates
the branch on the real worktree and switches its HEAD, hijacking the
in-progress rebase and trashing the working tree. (In the main worktree
git doesn't set GIT_DIR for rebase exec, which is why the bug was only
visible from linked worktrees.)

Using self.env also incidentally restores GIT_CONFIG_GLOBAL for shell
commands, so commits made via RunShellCommand are now authored by the
test config's CI identity rather than whatever the host's ~/.gitconfig
resolves to.
2026-05-25 15:18:18 +02:00
Stefan Haller cb0ecda3e4 Disable gh telemetry when running integration tests 2026-05-05 18:42:28 +02:00
Stefan Haller 6663867bb5 Change keybinding syntax to spell out full modifier names, and use + instead of -
The change to filter_menu_by_keybinding.go is needed because + now occurs in
many keybindings, so pick a different one that occurs only once.
2026-04-30 22:38:53 +02:00
Stefan Haller 196e0a3c17 Copy gocui files into lazygit repo under pkg/gocui
I copied all files except dot files (.github and .gitignore), the _examples
folder, and go.mod/go.sum.

At some point we may want to copy the files back to the gocui repo when other
clients (e.g. lazydocker) want to use the newer versions of them.
2026-04-30 14:29:08 +02:00
Karol ZwolakandStefan Haller 3892c40666 feat: add fork remote command
The command allows you to quickly add a fork remote by replacing the owner in the origin URL and optionally check out a branch from new remote.
2025-11-16 17:26:00 +01:00
phaniumandStefan Haller d88f95275f Modernize all codes
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./...
2025-11-15 10:46:23 +01:00
Stefan Haller 0904bf9969 Add test demonstrating the problem
When dropping changes to the submodule, we expect it to get rolled back to the
previous version; however, it is removed entirely instead.
2025-10-10 12:55:58 +02:00
Stefan Haller 21483b259c Rename AddFileInWorktree to AddFileInWorktreeOrSubmodule
It works for submodules too.

Also, pass file name and file content explicitly; the existing tests don't care
about these, but when writing tests that do, it makes them easier to understand.
2025-10-10 12:55:58 +02:00
Stefan Haller b413710d8c Add separate keybindings for confirmMenu and confirmSuggestion
It seems useful to have the flexibility to remap "enter" in confirmations to
"y", but keep "enter" for menus and suggestions (even though we sometimes use
menus as confirmations, but it's still good to give users the choice).
2025-09-05 10:42:04 +02:00
Stefan Haller 81868de264 Hard-code "enter" for adding lines in integration tests
This one doesn't make a difference in practice because we don't remap the key in
tests, but if we would, then this would no longer work correctly. It's just more
correct this way.
2025-09-05 10:42:04 +02:00
Stefan Haller 5a630aeda1 Refactor: add a separate Prompt view
So far, confirmations and prompts were handled by the same view, context, and
controller, with a bunch of conditional code based on whether the view is
editable. This was more or less ok so far, since it does save a little bit of
code duplication; however, now we need separate views, because we don't have
dynamic keybindings, but we want to map "confirm" to different keys in
confirmations (the "universal.confirm" user config) and prompts (hard-coded to
enter, because it doesn't make sense to customize it there).

It also allows us to get rid of the conditional code, which is a nice benefit;
and the code duplication is actually not *that* bad.
2025-09-05 10:42:03 +02:00
kyu08andStefan Haller 3fa5a8eddd Add "CopyToClipboard" command to ConfirmationController 2025-08-15 17:17:06 +02:00
Stefan Haller 8515c74722 Add test that demonstrates problem with showing filtered history of file with renames
The test shows that selecting a commit before the rename shows an empty diff,
and selecting the rename itself shows an added file rather than a rename.
2025-07-27 12:05:41 +02:00
Stefan Haller df48667253 Add a prompt for the sort order menus for branches 2025-07-09 13:16:42 +02:00
Stefan Haller 0471dbaa84 Enable intrange linter, and fix warnings 2025-06-30 18:30:11 +02:00
Stefan Haller 1e92d8b7f3 Enable nolintlint linter, and fix warnings 2025-06-30 18:30:11 +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 efcd71b296 Allow chaining of FileSystem methods 2025-04-09 10:27:57 +02:00
BrandonandStefan Haller 2db0a024bc Add integration test 2025-04-07 09:42:19 +02:00
Chris McDonnell ab23539c0c Add option to copy commit message body 2025-02-17 18:43:39 +01:00
AzraelSecandStefan Haller 6065908b0d Improve and adapt commit persistence test-cases 2025-02-07 09:28:27 +01:00
Anvar UmuralievandJesse Duffield 7db8fb8e9c Add option to delete local and remote tag 2025-01-30 09:05:17 +11:00
Stefan Haller 33e81f717d Extend reset/rebase test to use upstream branch name that is different from local one
The easiest way to do that is to rename the local branch after pushing.

This shows various levels of brokenness for the reset and rebase to upstream
commands: both menu entries display the wrong upstream branch name in the menu
(the local one rather than the remote one); executing the rebase command works
correctly though, the rebase command uses the right branch name. Resetting
fails, though.

We'll fix this in the next commit.
2025-01-04 15:46:14 +01:00
Nathan BaulchandJesse Duffield 508cdb40a8 Fix typos 2025-01-03 10:50:36 +11:00
Stefan Haller f6f2a52dee Bump gocui and adapt lazygit code
Original commit message of the gocui change:

This fixes View.Size, Width and Height to be the correct (outer) size of a view
including its frame, and InnerSize/InnerWidth/InnerHeight to be the usable
client area exluding the frame. Previously, Size was actually the InnerSize (and
a lot of client code used it as such, so these need to be changed to InnerSize).
InnerSize, on the other hand, was *one* less than Size (not two, as you would
have expected), and in many cases this was made up for at call sites by adding 1
(e.g. in calcRealScrollbarStartEnd, parseInput, and many other places in the
lazygit code).

There are still some weird things left that I didn't address here:
- a view's lower-right coordinates (x1/y1) are one less than you would expect.
  For example, a view with a 2x2 client area like this:
    ╭──╮
    │ab│
    │cd│
    ╰──╯
  in the top-left corner of the screen (x0 and y0 both zero) has x1/xy at 3, not
  4 as would be more natural.
- a view without a frame has its coordinates extended by 1 on all sides; to
  illustrate, the same 2x2 view as before but without a frame, sitting in the
  top-left corder of the screen, has coordinates x0=-1, y0=-1, x1=2, y1=2. This
  is highly confusing and unexpected.

I left these as they are because they would be even more of a breaking change,
and also because they don't have quite as much of an impact on general app code.
2024-12-01 10:40:08 +01:00
Yaroslav HalchenkoandStefan Haller 4bbfe7b3cc [DATALAD RUNCMD] run codespell throughout fixing typos automagically
=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^

Signed-off-by: Yaroslav Halchenko <debian@onerussian.com>
2024-08-27 18:03:00 +02:00
Stefan Haller ccd39bb8ae Fix wrong test assertion text
If a `t.FileSystem().FileContent("file.txt", Equals("bla"))` assertion fails
because the file doesn't exist, the error would say

   Expected path 'file.txt' to not exist, but it does

which is very confusing.
2024-08-24 11:01:25 +02:00
Stefan Haller a7c97400c6 Add a test demonstrating the bug
After switching to another repo and then back to the original one, all
keybinding suggestions in the status bar are shown twice.
2024-06-23 12:28:42 +02:00
Stefan Haller 44160ef844 Only render visible portion of the screen for commits view 2024-06-23 11:54:21 +02:00
Stefan Haller 43e04febee Fix reporting of unexpected selections in integration tests
Expected and actual selection were swapped in the error message.
2024-06-14 13:26:14 +02:00
AzraelSecandStefan Haller 03a075c223 fix: typo in IsVisible assertion string 2024-06-07 22:51:16 +02:00
Stefan Haller 4f6d3fb592 Don't wait in integration tests when running in headless mode
There's no point in spending time waiting in this case, as nobody can see it.
2024-06-05 14:44:02 +02:00
Stefan Haller b91b40ba4d Add test demonstrating the problem with force-pushing in a triangular workflow
Our code doesn't realize that we need to prompt the user to force push, when the
branch is up-to-date with its upstream but not with the branch that we're
pushing to.
2024-05-19 09:44:38 +02:00
Stefan Haller c4927e21c5 Rename PushBranch to PushBranchAndSetUpstream
It is unexpected that a function called PushBranch also sets the upstream
branch; also, we want to add a PushBranch function in the next commit that
doesn't.
2024-05-19 09:44:38 +02:00
Jesse Duffield fdff2dec79 Remove redundant variable dedeclarations
In go 1.22, loop variables are redeclared with each iteration of the
loop, rather than simple updated on each iteration. This means that we
no longer need to manually redeclare variables when they're closed over
by a function.
2024-05-19 16:38:21 +10:00
Stefan Haller a7041cf492 Allow editing a custom command from the suggestions list by pressing 'e'
For custom commands it is useful to select an earlier command and have it copied
to the prompt for further editing. This can be done by hitting 'e' now.

For other types of suggestion panels we don't enable this behavior, as you can't
create arbitrary new items there that don't already exist as a suggestion.
2024-05-19 07:06:18 +02:00
Stefan Haller da3e0f7147 Support deleting items from the custom commands history
In the custom commands panel you can now tab to the suggestions and hit 'd' to
delete items from there. Useful if you mistyped a command and don't want it to
appear in your history any more.
2024-05-19 07:06:18 +02:00
thirdkeywordandStefan Haller 1c098ff82a pkg: fix some typos
Signed-off-by: thirdkeyword <fliterdashen@gmail.com>
2024-04-20 13:47:39 +02:00
Stefan Haller e6a07b3f03 Add integration test that accesses commit properties in a custom command
Useful as a regression test to check that the following commit doesn't break it.
2024-04-12 08:33:47 +02:00
Eng Zer Jun f933a2f7ec Replace min/max helpers with built-in min/max
We upgraded our minimum Go version to 1.21 in commit
57ac9c2189. We can now replace our
`utils.Min` and `utils.Max` functions with the built-in `min` and `max`.

Reference: https://go.dev/ref/spec#Min_and_max
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2024-04-07 23:24:10 +08:00
Jesse Duffield c3f0b5cb4a Update interactive rebase demo
I'm adding an explicit delay between moving the commits and selecting
the next items because otherwise it happens too fast
2024-03-23 20:45:51 +11:00
Stefan Haller 1ec87364fe Add integration test 2024-03-11 09:19:11 +01:00