mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-24 10:13:41 -05:00
Reject pager entries that combine multiple diff mechanisms
A pager (GIT_PAGER) formats the diff git produces, while externalDiffCommand and useExternalDiffGitConfig change how git produces the diff in the first place. They are different pipeline stages, not alternatives, so combining them on one entry just pipes one through the other and produces garbled output (e.g. delta trying to parse difftastic's side-by-side output as a unified diff). The two external mechanisms likewise conflict, with the explicit command silently shadowing the git config one. Treat all three as mutually exclusive and reject configs that set more than one on the same entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9739a43355
commit
81420ce362
@@ -361,6 +361,9 @@ git:
|
||||
# # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
# useExternalDiffGitConfig: false
|
||||
#
|
||||
# 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually
|
||||
# exclusive; set at most one per entry.
|
||||
#
|
||||
# See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
|
||||
# for more information.
|
||||
pagers: []
|
||||
|
||||
@@ -71,7 +71,7 @@ git:
|
||||
- externalDiffCommand: difft --color=always
|
||||
```
|
||||
|
||||
The `colorArg` and `pager` options are not used in this case.
|
||||
The `colorArg` option is not used in this case.
|
||||
|
||||
You can add whatever extra arguments you prefer for your difftool; for instance
|
||||
|
||||
@@ -91,6 +91,8 @@ git:
|
||||
|
||||
This can be useful if you also want to use it for diffs on the command line, and it also has the advantage that you can configure it per file type in `.gitattributes`; see https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
|
||||
`pager`, `externalDiffCommand`, and `useExternalDiffGitConfig` are alternative ways of producing the diff, so a pager entry may use at most one of them.
|
||||
|
||||
## Emulating custom pagers on Windows
|
||||
|
||||
There is a trick to emulate custom pagers on Windows using a Powershell script configured as an external diff command. It's not perfect, but certainly better than nothing. To do this, save the following script as `lazygit-pager.ps1` at a convenient place on your disk:
|
||||
|
||||
@@ -275,6 +275,8 @@ type GitConfig struct {
|
||||
// # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.
|
||||
// useExternalDiffGitConfig: false
|
||||
//
|
||||
// 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually exclusive; set at most one per entry.
|
||||
//
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md for more information.
|
||||
Pagers []PagingConfig `yaml:"pagers"`
|
||||
// Config relating to committing
|
||||
|
||||
@@ -46,6 +46,9 @@ func (config *UserConfig) Validate() error {
|
||||
[]string{"always", "never", "when-maximised"}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validatePagers(config.Git.Pagers); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateKeybindings(config.Keybinding); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -71,6 +74,30 @@ func validateSpinner(spinner SpinnerConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// validatePagers rejects pager entries that combine more than one diff
|
||||
// mechanism. A pager (GIT_PAGER) formats the diff that git produces, whereas
|
||||
// externalDiffCommand and useExternalDiffGitConfig change how git produces the
|
||||
// diff in the first place; piping one through the other almost always yields
|
||||
// garbled output, so we treat the three as mutually exclusive.
|
||||
func validatePagers(pagers []PagingConfig) error {
|
||||
for i, pager := range pagers {
|
||||
count := 0
|
||||
if pager.Pager != "" {
|
||||
count++
|
||||
}
|
||||
if pager.ExternalDiffCommand != "" {
|
||||
count++
|
||||
}
|
||||
if pager.UseExternalDiffGitConfig {
|
||||
count++
|
||||
}
|
||||
if count > 1 {
|
||||
return fmt.Errorf("git.pagers[%d]: at most one of 'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' may be set; they are mutually exclusive", i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateEnum(name string, value string, allowedValues []string) error {
|
||||
if slices.Contains(allowedValues, value) {
|
||||
return nil
|
||||
|
||||
@@ -323,3 +323,34 @@ func TestUserConfigValidate_spinnerFrames(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserConfigValidate_pagers(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
pager PagingConfig
|
||||
valid bool
|
||||
}{
|
||||
{name: "empty", pager: PagingConfig{}, valid: true},
|
||||
{name: "pager only", pager: PagingConfig{Pager: "delta"}, valid: true},
|
||||
{name: "external diff command only", pager: PagingConfig{ExternalDiffCommand: "difft"}, valid: true},
|
||||
{name: "git config external diff only", pager: PagingConfig{UseExternalDiffGitConfig: true}, valid: true},
|
||||
{name: "pager and external diff command", pager: PagingConfig{Pager: "delta", ExternalDiffCommand: "difft"}, valid: false},
|
||||
{name: "pager and git config external diff", pager: PagingConfig{Pager: "delta", UseExternalDiffGitConfig: true}, valid: false},
|
||||
{name: "both external diff mechanisms", pager: PagingConfig{ExternalDiffCommand: "difft", UseExternalDiffGitConfig: true}, valid: false},
|
||||
{name: "all three", pager: PagingConfig{Pager: "delta", ExternalDiffCommand: "difft", UseExternalDiffGitConfig: true}, valid: false},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
config := GetDefaultConfig()
|
||||
config.Git.Pagers = []PagingConfig{s.pager}
|
||||
err := config.Validate()
|
||||
|
||||
if s.valid {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@
|
||||
"$ref": "#/$defs/PagingConfig"
|
||||
},
|
||||
"type": "array",
|
||||
"description": "Array of pagers. Each entry has the following format:\n\n # Value of the --color arg in the git diff command. Some pagers want\n # this to be set to 'always' and some want it set to 'never'\n colorArg: \"always\"\n\n # e.g.\n # diff-so-fancy\n # delta --dark --paging=never\n # ydiff -p cat -s --wrap --width={{columnWidth}}\n pager: \"\"\n\n # e.g. 'difft --color=always'\n externalDiffCommand: \"\"\n\n # If true, Lazygit will use git's `diff.external` config for paging.\n # The advantage over `externalDiffCommand` is that this can be\n # configured per file type in .gitattributes; see\n # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.\n useExternalDiffGitConfig: false\n\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md for more information."
|
||||
"description": "Array of pagers. Each entry has the following format:\n\n # Value of the --color arg in the git diff command. Some pagers want\n # this to be set to 'always' and some want it set to 'never'\n colorArg: \"always\"\n\n # e.g.\n # diff-so-fancy\n # delta --dark --paging=never\n # ydiff -p cat -s --wrap --width={{columnWidth}}\n pager: \"\"\n\n # e.g. 'difft --color=always'\n externalDiffCommand: \"\"\n\n # If true, Lazygit will use git's `diff.external` config for paging.\n # The advantage over `externalDiffCommand` is that this can be\n # configured per file type in .gitattributes; see\n # https://git-scm.com/docs/gitattributes#_defining_an_external_diff_driver.\n useExternalDiffGitConfig: false\n\n'pager', 'externalDiffCommand', and 'useExternalDiffGitConfig' are mutually exclusive; set at most one per entry.\n\nSee https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md for more information."
|
||||
},
|
||||
"commit": {
|
||||
"$ref": "#/$defs/CommitConfig",
|
||||
|
||||
Reference in New Issue
Block a user