-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Clean up the configuration of where a custom command's output goes #4525
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
Conversation
Looking at these again, I needed a moment to remember what they do, so make this more obvious to help future readers.
…menus We only validate the commands at top level right now.
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferencesFootnotes
|
deb1cbe to
63f755a
Compare
|
Some thorough manual testing of this would be good to make sure that all the credential handling stuff still works, and GPG signing. I don't use either, so I don't even know how to test that... |
|
So the removal of |
| self.c.LogAction(self.c.Tr.Actions.CustomCommand) | ||
|
|
||
| if customCommand.Stream != nil && *customCommand.Stream { | ||
| if customCommand.Output != nil && *customCommand.Output == "log" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth defining these literals log, popup, none as a constant somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure; we aren't doing this for any of the other existing enum configs either.
At one point I looked into replacing those string fields with enums, but couldn't find a good way to do that. Maybe it's still useful to use constants instead of string literals even though we can't enforce their use, but if we do that, I think we should do it consistently for all our configs, and that's out of scope for this PR.
|
|
||
| if err := validateCustomCommands(customCommand.CommandMenu); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add validation here that the user has not done pty: true with subprocess: true, or output not equal to log?
I don't see any protections against:
Only used when output is set to 'log', and subprocess is false.
from the docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's true that this is missing, but we also don't validate that stream: true (or now output: log) can't be used together with subprocess: true. And I was reluctant to do that because it could render existing config files invalid which used to load successfully before, and that could be annoying.
But it only just occurred to me that we can avoid these questions by taking it one step further and removing the subprocess and pty configs too, including them in the output enum too. It would then become output: none | terminal | log | logWithPty | popup. I like this idea a lot, it would simplify the custom command type further. @jesseduffield Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a new version that does this. No fixups, sorry, that wasn't feasible.
| if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" && output == "" { | ||
| output = "popup" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a migration path to output: none from when the existing config had streamValue explicitly set to false. Do we need that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think this was needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give me some details of why it isn't needed? Given the intent of previous streamValue having, false, true, nil, it seems we would cause issues for some people by removing the distinction between nil and false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would cause issues for some people
What kind of issues do you have in mind? Omitting 'stream' and setting stream to false has exactly the same effect, as does omitting 'output' and setting 'output' to none. I don't see the point of preserving the fact that they explicitly provided the default value.
In general we recommend against putting default values in your config file, see #4401 (comment). (Yes, that person responding to that comment disagrees, but I'd wager that's a small minority.)
Honestly, in this case I don't care too much either way, because I think it's extremely unlikely that someone put stream: false in their config file anyway. However, it's a little bit more complex to maintain the precedence of the three options in the migrator if we do it this way, and I just don't think it's worth it.
pkg/config/user_config.go
Outdated
| // [dev] Pointer to bool so that we can distinguish unset (nil) from false. | ||
| ShowOutput *bool `yaml:"showOutput"` | ||
| // The title to display in the popup panel if showOutput is true. If left unset, the command will be used as the title. | ||
| // Where the output of the command should go. 'none' discards it, 'log' shows it in the command log, and 'popup' shows it in a popup. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth mentioning that 'log' will stream the output whereas 'popup' will only show the output after the command has finished
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? This feels like a matter of course to me. With 'log', we stream because it's easy to do and it would be kind of silly not to, but it isn't essential. And for 'popup' it makes little sense to stream the output to the popup window (although technically we might be able to). Why do you think it needs mentioning?
(Happy to include this if it doesn't make the text a lot longer. Would you say it's enough to replace "'log' shows it in the command log" with "'log' streams it to the command log"?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just don't expect the user to have that level of understanding that we do about what makes sense. But yes I'm happy to say 'log streams it to the command log'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed in the new version
| output := "" | ||
| if streamKey, streamValue := yaml_utils.RemoveKey(node, "stream"); streamKey != nil { | ||
| if streamValue.Kind == yaml.ScalarNode && streamValue.Value == "true" { | ||
| output = "log" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interest of backwards compatibility, what are your thoughts on migrating everybody who's currently on 'stream: true' to both 'output: log' and 'pty: true'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My assumption is that people using stream: true did that because they wanted to see the output, not because they wanted to use a PTY (like me, when I discovered the issue). I think it makes sense to err on the side of what's probably best for most people, rather than what faithfully replicates the previous behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But how do we actually know what's best for most people? The fact that we've come this far without anybody complaining suggests that the current way actually is the best way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that we've come this far without anybody complaining
Huh? I am complaining, that's what started this whole change. I ran into a real problem (and a pretty annoying one at that, took me several days to sort it out), just because "stream: true" used a pty without me realizing it. This was caused by an updated tool (gh in this case) which suddenly started to do fancy things when running in a terminal, things that I don't want or need. This could happen to other people, and with other tools, and I want to spare them the frustration that I had.
Defaulting to no pty is the much more conservative default; the worst that can happen is that people lose the color output that they had before, which is not a big deal compared to the potential of misbehavior caused by running in a pty.
I added a breaking changes notice (e8d365f) to make people aware of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not mean to imply that you were not yourself complaining, my point was that we've come this far without any complaints prior, meaning lots of people may be happy with the current default.
Nevertheless you've persuaded me: it's much more painful to realise that you don't need a pty than vice versa, and it's possible for an issue to arise out of nowhere like it did with your gh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, left a couple questions
I'm following the rule of thumb that if there is only a single type that implements an interface, the interface is unnecessary and you can use the type directly. See https://100go.co/5-interface-pollution/ |
It is only implemented by *CmdObj, so use that directly in client code.
getCmdHandlerNonPty is defined for all platforms.
This decouples StreamOutput from whether a PTY is used. In most cases we just want to see the output in the log window, but don't have to use a PTY, e.g. for the bisect commands. This has the implication that custom commands that are using "stream: true" no longer use a PTY. In most cases that's probably a good thing, but we're going to add a separate pty config for those who really wanted this.
Co-authored-by: Chris McDonnell <[email protected]>
…o a single output enum
da8a9e7 to
3159e24
Compare
pkg/i18n/english.go
Outdated
| autoForwardBranches: none | ||
| If, on the other hand, you want this even for feature branches, you can set it to 'allBranches' instead.`, | ||
| "0.51.0": `- The 'subprocess', 'stream', and 'showOutput' fields of custom commands have been replaced by a single 'output' field. This should be transparent, if you used these in your config file it should have been automatically updated for you. There's one noteable change though: the 'stream' field used to mean both that the command's output would be streamed to the command log, and that the command would be run in a pseudo terminal (pty). We converted this to 'output: log', which means that the command's output will be streamed to the command log, but not use a pty, on the assumption that this is what most people wanted. If you do actually want to run a command in a pty, you can change this to 'output: logWithPty' instead.`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting this to 0.51 assuming that I won't merge it before Saturday's scheduled release.
…t use a pty any more
3159e24 to
e8d365f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@jesseduffield @ChrisMcD1 Do we think this has gotten enough manual testing to be comfortable merging it? Has either of you tried the above features? |
|
For pushing with credentials we do have an integration test, and it does indeed fail if you revert this hunk, so I think we're fine there. It is implemented using this fake pre-push hook that pretends to be the password prompt, which I think was a pretty smart idea. I don't see how we can write an integration test for GPG signing though, at least not for the case where it prompts you for a passphrase. It suspends to the terminal in that case, and we don't have any way to type the necessary characters in response to the prompt from within an integration test. So the only test we could write here is one where no passhrase is requested, and the config file contains |
|
Just tested GPG signing manually: brew install gnupg
# Make a throw‑away key (expiry 1 day)
gpg --quick-gen-key "Test User <[email protected]>" default default 1d
# Tell Git to use it
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '$1=="sec"{print $5;exit}')
git config --global user.signingkey "$KEYID"
git config --global commit.gpgsign true
git config --global gpg.program "$(which gpg)"
# Make a commit in lazygit, verify it asks for passphrase in a subprocess
# Verify the commit
git log -1 --show-signature
# Make another commit in lazygit, verify gpg caches the passphrase so you're not prompted again
# Set `git.overrideGpg: true` in lazygit config
# Make yet another commit, verify there's no issue creating the commit
# Disable caching of passphrase
gpgconf --kill gpg-agent
# Make another commit in lazygit, verify it completely breaks (as expected)
# Cleanup
TEST_EMAIL="[email protected]"
KEY_FP=$(gpg --list-secret-keys --with-colons "$TEST_EMAIL" | awk -F: '/^fpr:/ { print $10; exit }')
if [ -z "$KEY_FP" ]; then
echo "No secret key found for: $TEST_EMAIL"
exit 1
fi
echo "Deleting GPG key: $KEY_FP ($TEST_EMAIL)"
gpg --batch --yes --delete-secret-and-public-key "$KEY_FP"
gpgconf --kill gpg-agent |
|
Awesome, thanks. I guess we're good to merge then? |
I'm not a user of custom commands at all right now, so I'm not in a place to put this through its paces. But the code LGTM |
Yep |
…or a passphrase (#4586) Fix a regression introduced with #4525. This fixes the problem that background fetching makes lazygit hang when the fetch request needs to prompt for a passphrase. For Mac users who use the keychain to store their ssh passphrases, this can happen when lazygit is running while the machine goes to sleep, because macOS looks the keychain in that case.
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 [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4525 - Add custom patch command "Move patch into new commit before the original commit" by [@​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 [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4544 - Add an alternate keybinding (default <c-s>) for ConfirmInEditor by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4532 - Print migration changes to the console when migrating config file by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4548 ##### Fixes 🔧 - Migrate deprecated AllBranchesLogCmd to AllBranchesLogCmds by [@​ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4345 - Clear preserved commit message when entering CommitEditorPanel by [@​ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4558 - Split behavior of rendering allBranchesLogCmd and switching to next cmd by [@​ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4574 - Fix possible crash with auto-forwarding branches by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4565 - Fix main view occasionally scrolling to the top on its own when focused by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4573 - Fix home and end keys in prompts by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4554 - Fix crash when clicking in the status view by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4567 ##### Maintenance ⚙️ - Clean up utils package by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4538 ##### Docs 📖 - reword documentation for git.autoForwardBranches by [@​sean-xyz](https://github.com/sean-xyz) in jesseduffield/lazygit#4545 #### New Contributors - [@​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-->

Previously, custom commands had a
streamfield that was overloaded with two meanings: 1) it made the command's output appear in the log view, and 2) it used a pty for running the command. It makes sense to be able to configure these independently, so add a separateptyfield (although that's probably rarely needed in practice).Also, the
streamandshowOutputfields were conflicting; they could be used together, but when setting them both to true, the popup would always show "empty output", so this doesn't make sense. Combine them both into a singleoutputproperty with the possible values "none", "log", or "popup".We still have some more redundancy here, for example pty is only used when output is set to "log", and neither output nor pty are used when subprocess is true. But I stopped there, because I think this is already an improvement over the previous state.
go generate ./...)