Skip to content

Print migration changes to the console when migrating config file #4548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 21, 2025

Conversation

stefanhaller
Copy link
Collaborator

  • PR Description

This might be useful to see in general (users will normally only see it after they quit lazygit again, but still). But it is especially useful when writing back the config file fails; some users have their config file in a read-only location, so we had reports of lazygit no longer starting up when migration was necessary. #4210 was supposed to improve this a bit, but it didn't tell users what changes need to be made to the config file. Now we tell them, and users can then make these changes manually if they want.

We do this only at startup, when the GUI hasn't started yet. This is probably good enough, because it is much less likely that writing back a migrated repo-local config fails because it is not writeable.

Example output:

The user config file /Users/stk/Library/Application Support/lazygit/config.yml must be migrated. Attempting to do this automatically.
The following changes were made:

- Renamed 'gui.windowSize' to 'screenMode'
- Changed 'null' to '<disabled>' for keybinding 'keybinding.universal.confirmInEditor'
- Changed 'stream: true' to 'output: log' in custom command

Config file saved successfully to /Users/stk/Library/Application Support/lazygit/config.yml

The branch also contains a lot of code cleanups.

  • Please check if the PR fulfills these requirements
  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalised (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc

@stefanhaller stefanhaller requested a review from jesseduffield May 9, 2025 09:03
@stefanhaller stefanhaller added the enhancement New feature or request label May 9, 2025
@stefanhaller
Copy link
Collaborator Author

@ChrisMcD1 You have been around in this code a lot, feel like reviewing this?

@stefanhaller stefanhaller force-pushed the print-migration-changes branch from ca02207 to 2e4ba67 Compare May 9, 2025 09:05
Copy link

codacy-production bot commented May 9, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for 1fbfefa1 64.89%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (1fbfefa) Report Missing Report Missing Report Missing
Head commit (cabcd54) 56435 49006 86.84%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#4548) 94 61 64.89%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

@ChrisMcD1
Copy link
Contributor

What do you think about printing the entire file contents of the new file?
Could be useful if someone just wants to copy and paste that into whatever system sets up their config file.
Telling them what we are doing in text is surely helpful, but they'll still need to recreate those changes in order to launch lazygit. Might as well help them along that journey.

@stefanhaller
Copy link
Collaborator Author

What do you think about printing the entire file contents of the new file?

Hm, I don't know. My config file is pretty long, I don't think I would want it printed entirely. Especially if I then can't tell what changed. (And some people have copied the entire default config into their config file.)

Also, most people running into the issue with read-only config files seem to be using home-manager, and from what I understand a copy of the entire config doesn't help them, because they need to enter it in home-manager's own format. (I might have gotten that wrong though.)

At first I had toyed with the idea of printing a diff, and actually had that working, but I found that a context diff is less useful than I thought, because in longer sections you can't see which section you're in; so that's why I settled on the current approach of printing change instructions.

}

// Add more migrations here...

if reflect.DeepEqual(rootNode, originalCopy) {
return content, nil
return nil, false, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to switch to returning nil in all cases when we don't make changes, could we just use a check against changedContent == nill instead?

No strong preference for that, I just thought of the idea

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, that's what I initially did. It has the theoretical problem that if we ever write a migrator that only removes a key without replacement, then you can't distinguish the case that nothing was done from the case that the config file only contained that key, and we removed it. (You might argue that the Yaml library will probably return an empty bytes slice instead of nil in that case, so we could still distinguish that, but I'm actually not sure if that's really the case, and I don't think we should rely on it.)

The extra bool is a bit clearer and safer.

Comment on lines 237 to 239
for pair := changes.Oldest(); pair != nil; pair = pair.Next() {
changesText += fmt.Sprintf("- %s\n", pair.Key)
}
Copy link
Contributor

@ChrisMcD1 ChrisMcD1 May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this library has support for iterators, so this could be more cleanly expressed as:

for change := range changes.KeysFromOldest() {
    changesText += fmt.Sprintf("- %s\n", change)
}

https://github.com/wk8/go-ordered-map?tab=readme-ov-file#iterator-support-go--123

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's only available in master though, not in the latest release that we're using (which is from 2023). I didn't want to update to the master version.

It's becoming less of an issue now that we encapsulate this in the generics module, see below.

@@ -220,7 +221,9 @@ func loadUserConfig(configFiles []*ConfigFile, base *UserConfig, isGuiInitialize
// from one container to another, or changing the type of a key (e.g. from bool
// to an enum).
func migrateUserConfig(path string, content []byte, isGuiInitialized bool) ([]byte, error) {
changedContent, didChange, err := computeMigratedConfig(path, content)
changes := orderedmap.New[string, bool]()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do a bool instead of an struct{}? I don't know my idiomatic go that well, but I thought struct{} was how to say "I want a set, but that doesn't exist in go, so my values are empty"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question; I simply modelled this after generics/set.Set without thinking much about it. I suppose in that case it was done with a bool because it makes checking for containment slightly easier (return set.m[value] rather than _, found := set.m[value]; return found).

Anyway, this discussion shows that we shouldn't use a map in client code, but provide a proper OrderedSet abstraction instead; I was just too lazy to do that initially. See jesseduffield/generics#2 (still using a bool there, simply for consistency with set, but it's now an implementation detail and doesn't matter), and 0138b9e.

@stefanhaller stefanhaller force-pushed the print-migration-changes branch from 2e4ba67 to 0138b9e Compare May 10, 2025 11:58
@stefanhaller stefanhaller added the blocks-release Must be addressed before we can cut the next release label May 17, 2025
@stefanhaller stefanhaller force-pushed the print-migration-changes branch from 0138b9e to b317b9e Compare May 17, 2025 13:43
@stefanhaller
Copy link
Collaborator Author

It looks like the discussion has stalled. @ChrisMcD1, I think your concerns above have all been addressed, is that true? Any further thoughts from your side?

@jesseduffield Are you interested in reviewing this too?

Copy link
Contributor

@ChrisMcD1 ChrisMcD1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, looks good to me!

Copy link
Owner

@jesseduffield jesseduffield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

It's a bit silly to find out by string comparison whether computeMigratedConfig
did something, when it knows this already and can just return the information.

This doesn't make a huge difference to the production code; the string
comparison isn't very expensive, so this isn't a big deal. However, it makes the
tests clearer; we don't have to bother specifying an expected output string if
the didChange flag is false, and in particular we can get rid of the ugly "This
test intentionally uses non-standard indentation" bit in one of the tests.
Most migrations happen at startup when loading the global config file, at a time
where the GUI hasn't been initialized yet. We can safely print to the console at
that point. However, it is also possible that repo-local config files need to be
migrated, and this happens when the GUI has already started, at which point we
had better not print anything to stdout; this totally messes up the UI.

In this commit we simply suppress the logging when the GUI is running already.
This is probably good enough, because the logging is mostly useful in the case
that writing back the migrated config file fails, so that users understand
better why lazygit doesn't start up; and this is very unlikely to happen for
repo-local config files, because why would users make them read-only.
This might be useful to see in general (users will normally only see it after
they quit lazygit again, but still). But it is especially useful when writing
back the config file fails for some reason, because users can then make these
changes manually if they want.

We do this only at startup, when the GUI hasn't started yet. This is probably
good enough, because it is much less likely that writing back a migrated
repo-local config fails because it is not writeable.
This is for the unlikely case that a repo-local config file can't be written
back after migration; in this case we can't log the migration changes to the
console, so include them in the error popup instead.
@stefanhaller stefanhaller force-pushed the print-migration-changes branch from b317b9e to cabcd54 Compare May 21, 2025 06:51
@stefanhaller stefanhaller enabled auto-merge May 21, 2025 06:51
@stefanhaller stefanhaller merged commit 7a24c56 into master May 21, 2025
14 checks passed
@stefanhaller stefanhaller deleted the print-migration-changes branch May 21, 2025 06:54
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request May 23, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit) | minor | `v0.50.0` -> `v0.51.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jesseduffield/lazygit (jesseduffield/lazygit)</summary>

### [`v0.51.0`](https://github.com/jesseduffield/lazygit/releases/tag/v0.51.0)

[Compare Source](jesseduffield/lazygit@v0.50.0...v0.51.0)

<!-- Release notes generated using configuration in .github/release.yml at v0.51.0 -->

#### What's Changed

##### Enhancements 🔥

-   Clean up the configuration of where a custom command's output goes by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4525
-   Add custom patch command "Move patch into new commit before the original commit" by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4552
-   Make '>' first jump to the beginning of the branch, and only then to the first commit by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4544
-   Add an alternate keybinding (default <c-s>) for ConfirmInEditor by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4532
-   Print migration changes to the console when migrating config file by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4548

##### Fixes 🔧

-   Migrate deprecated AllBranchesLogCmd to AllBranchesLogCmds by [@&#8203;ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4345
-   Clear preserved commit message when entering CommitEditorPanel by [@&#8203;ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4558
-   Split behavior of rendering allBranchesLogCmd and switching to next cmd by [@&#8203;ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4574
-   Fix possible crash with auto-forwarding branches by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4565
-   Fix main view occasionally scrolling to the top on its own when focused by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4573
-   Fix home and end keys in prompts by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4554
-   Fix crash when clicking in the status view by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4567

##### Maintenance ⚙️

-   Clean up utils package by [@&#8203;stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4538

##### Docs 📖

-   reword documentation for git.autoForwardBranches by [@&#8203;sean-xyz](https://github.com/sean-xyz) in jesseduffield/lazygit#4545

#### New Contributors

-   [@&#8203;sean-xyz](https://github.com/sean-xyz) made their first contribution in jesseduffield/lazygit#4545

**Full Changelog**: jesseduffield/lazygit@v0.50.0...v0.51.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4yMi4wIiwidXBkYXRlZEluVmVyIjoiNDAuMjMuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocks-release Must be addressed before we can cut the next release enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants