1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2026-05-22 10:15:43 +02:00
Commit Graph

7489 Commits

Author SHA1 Message Date
Stefan Haller 52ffc5465a Remove the invitation to submit PRs from the issue template 2026-05-11 16:02:35 +02:00
Stefan Haller 353e3a1e4a Dont log GitHub PR fetching errors to the Command log (#5600)
In the Command log we only want to see errors for user-initiated
actions, not from background activity.
2026-05-10 15:49:43 +02:00
Stefan Haller 58abf24862 Log errors from fetching GitHub PRs to the debug log, not to the Command Log
In the Command Log we only want to see errors for user-initiated actions, not
from background activity.
2026-05-10 15:47:02 +02:00
Stefan Haller d9aceaf0da Keep GitHub PR refresh error logging in one place 2026-05-10 15:40:09 +02:00
Stefan Haller 18ddc9ca9c Support GitHub Enterprise for the Pull Requests feature (#5596)
The feature to show PR icons in the branches list only worked for
github.com, but not for GitHub Enterprise remotes. This PR makes that
work, if you configure a services entry for it as explained
[here](https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-pull-request-urls).

Prior art: #5559.
2026-05-10 15:30:54 +02:00
Stefan Haller 692f56a61b Optimize regex compilations
Compile them only once at startup. I didn't measure if this makes a difference,
but it's easy to do, and now that we potentially need to check them more often,
it might be worth it.
2026-05-10 15:28:14 +02:00
Stefan Haller eba1df11a8 Document that the services entry also enables GHE pull-request icons
The services config has been the path for GHE for a while (for the
View-PR-URL feature) but it now does double duty: it's also what enables
the branches-panel PR icons for non-github.com hosts. Worth calling out
explicitly so users don't assume it's still github.com-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:28:14 +02:00
Stefan Haller d955ba8fb8 Remove now unused code
Doing this in a separate commit makes the previous commit's diff easier to read.
2026-05-10 15:28:14 +02:00
Stefan Haller 1c79fe24d0 Support GitHub Enterprise for the pull-requests feature
The branches-panel PR icons only worked for github.com remotes. There was no
fundamental reason — the auth library we already vendor (cli/go-gh) supports
enterprise tokens out of the box (GH_ENTERPRISE_TOKEN, gh auth's keyring),
and the user-facing 'services' config has long been the documented way to
tell lazygit "this domain is a github service" for the View-PR-URL feature.

The fetcher just hardcoded github.com in three places:
- a substring check on the remote URL to decide we're "in a github repo",
- the GraphQL endpoint (always api.github.com/graphql), and
- the auth lookup (always against the default host).

Plumb the resolved web domain through instead. Detection now goes through
the hosting_service ("is this remote's provider 'github'?"), which means a
user with services: { 'git.acme.com': 'github:git.acme.com' } configured
gets PR icons on their GHE remotes too.

Replacing the substring check with a provider check also tightens a latent
bug in getGithubRemotes: it previously accepted any remote whose URL parsed
with the default regex, including gitlab and bitbucket — masked today only
by the InGithubRepo gate, but exposed once the gate goes away.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:28:14 +02:00
Stefan Haller 21d58085f4 Expose service info (provider, host, owner, repo) from the hosting service
The github pull-request fetcher needs to know whether a given remote is a
github-type service, which host its API lives on, and which owner/repo to
query against. Today the fetcher hardcodes the first two ("does the URL
contain github.com" and "https://api.github.com/graphql") and re-derives
owner/repo from the remote, which precludes GitHub Enterprise and makes
the fetch entry point take more arguments than it needs.

Add an accessor on the hosting service manager that exposes the already-
resolved service domain together with the parsed owner/repo, so callers
can answer all of these questions without reaching into the manager's
internals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:28:14 +02:00
Stefan Haller 88c540db12 Fix cherry-picking a range selection of commits (#5599)
After cherry-picking a commit, copying a range-selection of commits was
broken in that it would copy only the last selected commit rather than
all of them.
2026-05-09 14:08:20 +02:00
Stefan Haller 7a2d1ab544 Clear cherry-pick buffer when copying after a paste
After a successful paste DidPaste is true, hiding the "X commits copied"
indicator but leaving the buffer populated. From the user's perspective
this looks like a clean slate, so a new shift+C should start fresh. It is
important to reset DidPaste first, before populating the buffer with the new
commits, because otherwise each loop iteration would overwrite the previous one
since Add() rebuilds the set via SelectedHashSet() which returns empty while
DidPaste is set.
2026-05-09 14:02:42 +02:00
Stefan Haller f264d43a1a Add test for missing commits when range-copying after a paste
After a successful paste, the "X commits copied" indicator hides and
DidPaste is set, but the buffer is not cleared. If the user then
range-selects multiple commits and presses shift+C, every Add() call
rebuilds the set via SelectedHashSet(), which returns empty while
DidPaste is true; each iteration of the copy loop therefore overwrites
the previous one and only the last commit in the range survives.
2026-05-09 14:02:42 +02:00
Stefan Haller 1cab15eba8 Some additions to AGENTS.md 2026-05-09 14:02:42 +02:00
Stefan Haller 84be8e130f Improve inline spinner performance (#5592)
As a followup to #5571, improve performance for inline spinners too.

This requires a bit of preparation; in particular, we change
ListContextTrait.HandleRender to no longer force a UI layout/redraw, so
callers need to take care of this themselves where needed. This requires
careful testing to see that we didn't miss any situation where redrawing
only worked by accident; see the first commit of the branch for an
example.
2026-05-09 14:01:33 +02:00
Stefan Haller 4734bab896 Improve performance of inline status spinner
Now that HandleRender no longer does an implicit Render(), we can use it inside
OnUIThreadContentOnly to save performance, on the assumption that rerendering a
view that contains an inline spinner never changes the layout.
2026-05-09 13:58:33 +02:00
Stefan Haller 76211eea68 Remove Render() from ListContextTrait.HandleRender
self.c.Render() at the end of HandleRender was there to schedule a gocui Update
tick so the view content modified above would actually get drawn. For UI-thread
callers (the great majority -- keybinding handlers, the layout function itself,
popup resize, etc.) this was unnecessary work, since gocui already runs a
layout/redraw cycle after every event. SimpleContext.HandleRender doesn't call
Render() either, so this aligns the two implementations.

The few callers that drove HandleRender from a worker goroutine and relied on
Render() for the flush were wrapped in OnUIThread in the preceding commits, so
the implicit Render is no longer needed.

Also, Render() being called *before* setFooter() looks like it might have been a
theoretical race; this is no longer an issue now.
2026-05-09 13:58:33 +02:00
Antoine Gaudreau Simard 8675862228 Bounce setGithubPullRequests' Branches render to UI thread
Fixes an issue mostly noticeable using the go -race mode, this resolves
them.
2026-05-09 13:58:33 +02:00
Antoine Gaudreau Simard 225bcaa619 Bounce commit files selection render to UI thread
The redraw of the selection color (using <space>) would be tied to the
spinner drawing. To reproduce, having a high spinner refresh rate and
toggling a file would see a delay equivalent to the time spinner refresh
rate.
2026-05-09 13:58:33 +02:00
Stefan Haller 3d324ed7fb Bounce SuggestionsContext.SetSuggestions to UI thread
SetSuggestions has two callers: prepareConfirmationPanel calls it directly on
the UI thread, while editors.promptEditor and
SuggestionsContext.RefreshSuggestions call it via AsyncHandler, which runs the
result closure on a worker goroutine. The worker path currently relies on
HandleRender's self.c.Render() to flush the view update. Wrap the body in
OnUIThread so the worker path stays correct when Render() is removed; for the
UI-thread caller the extra bounce is harmless.
2026-05-09 13:58:33 +02:00
Stefan Haller a364a8d75c Bounce explicit LocalCommits render in refreshBranches to UI thread
refreshBranches runs on a worker goroutine and re-renders the commits view
directly to refresh the branch-head visualization. As with refreshView, this
currently only flushes because HandleRender ends with self.c.Render(). Wrap the
explicit HandleRender call (along with the LocalCommitsMutex pair around it) in
OnUIThread so it keeps working once Render() is removed.
2026-05-09 13:58:33 +02:00
Stefan Haller 0d1caf5c22 Bounce refreshView to the UI thread
An async refresh dispatches refreshXyz on a worker goroutine, which then calls
refreshView -> PostRefreshUpdate -> HandleRender. Today the final
self.c.Render() inside ListContextTrait.HandleRender is what triggers a UI flush
from the worker. We're going to remove that Render() call, so prepare by
wrapping refreshView's body in OnUIThread.

This moves the entire rendering of the view (and the ReApplyFilter/ReApplySearch
stuff) to the UI thread, not just the layout. I don't expect this to make a
difference in practice, and it is already one step towards my long-term goal of
moving all view rendering to the UI thread (see
https://github.com/jesseduffield/lazygit/issues/2974#issuecomment-1729154768).
2026-05-09 13:58:33 +02:00
Stefan Haller 79440c0945 Set the view color on the UI thread too
Unrelated to this branch, just because we're touching this code: there's little
reason to set the color on the background thread but the text on the UI thread.
Set them both together on the UI thread. Avoids a data race (unlikely to be a
problem in practice, we're talking about a 64-bit int, but still).
2026-05-09 13:58:33 +02:00
Stefan Haller 670565c175 Have renderAppStatus trigger a full layout when the appStatus width changes
In 0d195077e4 we improved the performance of the status bar spinner by
avoiding a layout. This is fine from one spinner tick to the next, but it's a
problem when spinning starts or ends (or in the hypothetical case that the
status text changes in the middle of the operation, which we never do in
lazygit, but theoretically could). In this case a layout is needed so that the
rest of the status bar gets pushed over appropriately (or moves back to the left
when the spinner ends), and also so that the bottom line is shown or hidden
properly for users who set gui.showBottomLine to false.

To fix this, keep track of the status string width and force a layout whenever
it changes. This includes the beginning and end of an operation when it changes
from empty to non-empty or vice versa.

There is currently no observable misbehavior from this bug, but that's only
because we must have a HandleRender call somewhere that forces a full layout
when an operation starts or ends. We will remove the Render() call from
HandleRender at the end of this branch, at which point the misbehavior would be
visible if we didn't fix it here.
2026-05-09 13:58:33 +02:00
Antoine Gaudreau Simard b3deef31ad When drawing tainted views in ForceFlushViewsContentOnly, also draw views that overlap them
This prevents views from drawing over higher z-order views.

Currently this is not an issue in practice, because we use
ForceFlushViewsContentOnly only for the bottom line status spinner, and there
are never views on top of it. However, later in the branch we will use the
mechanism to redraw the inline spinners in panels (e.g. the "Pushing..." status
next to a branch name), and there could be a popup on top of it.

Co-authored-by: Stefan Haller <stefan@haller-berlin.de>
2026-05-09 13:58:33 +02:00
Stefan Haller 4f0393f97b Fix visual glitch with status bar spinner at very slow spinner rates
With a very slow spinner rate (seconds), you can see that at the beginning of an
operation the bottom line leaves a gap for where the status will go, but the
status (and spinner) is only drawn the first time the spinner ticks. The reason
is that layout looks at GetStatusString to decide how much room to leave, rather
than at the actual content of the AppStatus view; the view content is only set
by renderAppStatus the first time the spinner ticks.

Fix this by making layout look at the actual content of the view so that the
layout is in sync with what is drawn. This also avoids flicker if an operation
is so fast that it finishes before the spinner ticks for the first time,
especially for users who set gui.showBottomLine to false.
2026-05-08 22:42:23 +02:00
Stefan Haller 49bb072088 Redraw only the spinner when nothing else has changed (#5571)
### PR Description
This fixes #4734, where lazygit would use a lot of CPU when the spinner
was shown due to redrawing the entire screen every time the spinner
needed a redraw.
The change adds the ability to request a UI redraw without invalidating
the full UI, thus only redrawing the spinner, re-routing the spinner to
this new flow.
CPU usage on a chromebook went from 60% to 5% when the spinner is shown.

Changing the refresh rate of the spinner from 50ms to 200ms brings it
down from 5% to 1% if ever we would like to change the default,
personally I prefer the slower moving spinner, but that's subjective.
2026-05-06 20:42:06 +02:00
Antoine Gaudreau Simard b7edcbad3a Improve performance of spinner in Synchronized events
Instead of redrawing the two views on each tick, only redraw the spinner
2026-05-06 20:38:53 +02:00
Stefan Haller 5dcc93e8cc Validate that gui.spinner.frames must all have the same width
The spinner looks weird if they don't. While we're at it, validate that frames
must not be empty, which would have crashed with a division by zero.
2026-05-06 18:53:32 +02:00
Antoine Gaudreau Simard 0d195077e4 Improve performance when drawing the spinner on background events 2026-05-06 18:53:32 +02:00
Antoine Gaudreau Simard 9c3e7dac88 Support to request a content-only UI refresh
This skips the whole-UI layout calculations, and lets tcell's dirty cell
handling redraw only changed cells.
2026-05-06 18:53:32 +02:00
Antoine Gaudreau Simard 79727f1780 Honor the spinner rate configurate with sync spinner 2026-05-06 18:53:32 +02:00
Stefan Haller 164f7da33d Fix missing layout call after switching repos
This didn't cause a bug so far because switching repos always happens from
within an OnWaitingStatus, so the spinner would take care of calling layout and
draw. However, later in this branch we are going to optimize the spinner so that
it no longer calls layout, at which point this would break, so make sure we
rerender at the point where it's needed.
2026-05-06 18:53:32 +02:00
Stefan Haller e1dff3ffa7 Fix the check_for_fixups.sh script again (#5590)
Our most recent change to the script (58309b02a9) broke it because the
anchored regex's no longer match the beginning of the subject. Fix this
by omitting the hash, which is a bit unfortunate but probably acceptable
(I rarely look at the output of the script anyway).
2026-05-06 18:53:12 +02:00
Stefan Haller af0cdf6d6e Fix the check_for_fixups.sh script again
Our most recent change to the script (58309b02a9) broke it because the
anchored regex's no longer match the beginning of the subject. Fix this by
omitting the hash, which is a bit unfortunate but probably acceptable (I rarely
look at the output of the script anyway).
2026-05-06 18:44:59 +02:00
Stefan Haller 434abc7994 Remove modifiers from keybinding (#5588)
Followup to #5563; I forgot to do this there.
2026-05-06 09:55:46 +02:00
Stefan Haller ee94e215e7 Remove dead Modifier field from keybindings
Modifiers were moved into Key in 22169e22f, but the separate Modifier field
on types.Binding and gocui.keybinding was left behind. The keypress matcher
already compares modifiers via Key.Equals, so the old field is never read on
the dispatch path; it just got passed through SetKeybinding and stored.

Drop it from gocui.keybinding, types.Binding, and the SetKeybinding /
DeleteKeybinding signatures, and remove every now-redundant Modifier:
gocui.ModNone struct field. Mouse bindings keep their own Modifier (on
ViewMouseBinding) since that path still consults it.
2026-05-06 09:51:23 +02:00
Stefan Haller 1bce7ed1c7 Remove unused function DeleteKeybinding
I noticed that it compares key.keyName and key.str separately instead of calling
key.Equals, but instead of deciding whether that's a problem, just delete the
function when nobody needs it.
2026-05-06 09:51:23 +02:00
Stefan Haller 6ed87bd5e4 Disable gh telemetry when running integration tests (#5587)
This prevents a file `test/.local/state/gh/device-id` from appearing in
the working copy after running integration tests locally.
2026-05-06 09:50:37 +02:00
Stefan Haller cb0ecda3e4 Disable gh telemetry when running integration tests 2026-05-05 18:42:28 +02:00
Stefan Haller 146f004918 Revert the change of <ctrl+j>/<ctrl+k> to <alt+down>/<alt+up> (#5582)
While I strongly prefer the alt-arrow bindings myself, I'm worried that
existing users might not be happy about the change, so I'm reverting it.

I'm working on supporting multiple keybindings for every command, so
once that's in, we can change the default to include both.
2026-05-04 18:25:16 +02:00
Stefan Haller 2332d9b27b Revert the change of <ctrl+j>/<ctrl+k> to <alt+down>/<alt+up>
While I strongly prefer the alt-arrow bindings myself, I'm worried that existing
users might not be happy about the change, so I'm reverting it.

I'm working on supporting multiple keybindings for every command, so once that's
in, we can change the default to include both.
2026-05-04 18:17:37 +02:00
Stefan Haller abe9e6c041 Add an AGENTS.md file (#5581) 2026-05-04 14:21:17 +02:00
Stefan Haller 9a2891818e Add an AGENTS.md file 2026-05-04 14:16:54 +02:00
Stefan Haller c6d73ace9a Show push URLs for remotes that have any (#5576)
In the Remotes panel, when selecting a remote that has push URLs, show
them in the main view in addition to the fetch URL(s).

Addresses half of #5566 (just the showing part, not the editing).
2026-05-04 13:13:17 +02:00
Stefan Haller 127dd9d325 Expose PushUrls to custom commands 2026-05-04 13:09:47 +02:00
Stefan Haller 6f1c57b604 Show PushUrls for selected remote if there are any 2026-05-04 13:09:47 +02:00
Stefan Haller d0ed65e0fd Add PushUrls field to models.Remote
Add some tests for RemoteLoader while we're at it; we didn't have any.
2026-05-04 13:09:47 +02:00
Stefan Haller 59b9b5959d Use more widely-supported Unicode symbols for the commit graph (#5573)
The commit graph used '⏣' (U+23E3 BENZENE RING WITH CIRCLE) for merge
commits and '◯' (U+25EF LARGE CIRCLE) for regular commits. Both have
very poor coverage in popular monospace fonts:

- '⏣' lives in the Misc Technical block and is essentially absent from
every common monospace font (Source Code Pro, JetBrains Mono, Fira Code,
Cascadia Code, Hack, Iosevka, Menlo, Consolas, Monaco, IBM Plex Mono,
Ubuntu Mono, Noto Sans Mono, Inconsolata). It is always drawn from a
system fallback font.
- '◯' is the late-addition LARGE CIRCLE codepoint. It is present in some
fonts (Cascadia, Fira Code, Hack, Iosevka, Menlo, Noto Sans Mono) but
missing from many others, including Source Code Pro and most Nerd Font
derivatives based on it.

This is why the graph renders inconsistently across platforms even when
the same monospace font is configured: each OS picks a different
fallback font (Apple Symbols on macOS, Segoe UI Symbol on Windows,
Noto/DejaVu/Symbola on Linux), and the substituted glyphs differ in
shape, weight, and advance width. '◯' is also East Asian Ambiguous
width, so some terminals render it wider than one cell, exaggerating the
misalignment.

Replace the symbols with codepoints from the foundational 1991 Geometric
Shapes block, which has far broader font coverage:

- Merge: '◎' U+25CE BULLSEYE -- concentric circles, the visually closest
cousin to the previous benzene-ring glyph.
- Commit: '○' U+25CB WHITE CIRCLE -- the same hollow-circle silhouette
as before, just a more universally available codepoint.

The new symbols are present in the font directly in significantly more
cases; and when fallback is still required, they are universally
well-drawn (unlike '⏣', which many fallback fonts also lack).

I also considered choosing suitable nerd font symbols for those who are
using nerd fonts, on the assumption that these must work better because
they are guaranteed to be in the font and no fallback font substitution
is necessary; several suitable icons could be considered, e.g.
`nf-cod-circle_large` or `nf-md-circle_double`. Surprisingly, these
didn't work well, and the reason is that (at least in the font I am
using) these are defined with a glyph width that is wider than their
advance width, which means they draw in different sizes depending on
whether they are followed by a space or not. The glyphs we picked above
don't have this problem.

And finally, I considered adding config options so that users with weird
fonts can pick symbols that work well for them. I would like to avoid
having to do this though; ideally we should be able to make a choice
that works well for everybody.
2026-05-04 13:09:28 +02:00
Stefan Haller 35d3659cce Use more widely-supported Unicode symbols for the commit graph
The commit graph used '⏣' (U+23E3 BENZENE RING WITH CIRCLE) for merge
commits and '◯' (U+25EF LARGE CIRCLE) for regular commits. Both have
very poor coverage in popular monospace fonts:

- '⏣' lives in the Misc Technical block and is essentially absent from
  every common monospace font (Source Code Pro, JetBrains Mono, Fira
  Code, Cascadia Code, Hack, Iosevka, Menlo, Consolas, Monaco, IBM
  Plex Mono, Ubuntu Mono, Noto Sans Mono, Inconsolata). It is always
  drawn from a system fallback font.
- '◯' is the late-addition LARGE CIRCLE codepoint. It is present in
  some fonts (Cascadia, Fira Code, Hack, Iosevka, Menlo, Noto Sans
  Mono) but missing from many others, including Source Code Pro and
  most Nerd Font derivatives based on it.

This is why the graph renders inconsistently across platforms even
when the same monospace font is configured: each OS picks a different
fallback font (Apple Symbols on macOS, Segoe UI Symbol on Windows,
Noto/DejaVu/Symbola on Linux), and the substituted glyphs differ in
shape, weight, and advance width. '◯' is also East Asian Ambiguous
width, so some terminals render it wider than one cell, exaggerating
the misalignment.

Replace the symbols with codepoints from the foundational 1991
Geometric Shapes block, which has far broader font coverage:

- Merge: '◎' U+25CE BULLSEYE -- concentric circles, the visually
  closest cousin to the previous benzene-ring glyph.
- Commit: '○' U+25CB WHITE CIRCLE -- the same hollow-circle silhouette
  as before, just a more universally available codepoint.

The new symbols are present in the font directly in significantly
more cases; and when fallback is still required, they are universally
well-drawn (unlike '⏣', which many fallback fonts also lack).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 13:06:29 +02:00