Skip to content

Commit e6bd9d0

Browse files
authored
Migrate deprecated AllBranchesLogCmd to AllBranchesLogCmds (#4345)
- **PR Description** Fixes #3961 Their issue where the default `allBranchesLogCmd` default remains present is because we just do a `lo.Uniq(lo.WithoutEmpty())` on the combined list of `allBranchesLogCmd` and `allBranchesLogCmds`. At the point of this code, it is not possible to tell whether the value present in `allBranchesLogCmd` is user-provided or not. We have already merged the config with the default config, so the user not setting anything, and the user explicitly setting "Yes, I want the default", are indistinguishable. Based on that bug report, I'm assuming that users that have not set anything for `allBranchesLogCmd`, but _have_ set something for `allBranchesLogCmds`, just want the list they have specified in the plural version. Some users have likely figured out they can explicitly set `allBranchesLogCmd: ""` to get this behavior, but most would not. To achieve this desired behavior, I figure it is easiest to just migrate all user config to `allBranchesLogCmds`. If they have explicitly set a non-empty value in `allBranchesLogCmd`, it will be pulled over. If they set an empty string, it will be excluded. - **Please check if the PR fulfills these requirements** * [X] Cheatsheets are up-to-date (run `go generate ./...`) * [X] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [X] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [X] Docs have been updated if necessary * [X] You've read through your own file changes for silly mistakes etc
2 parents c16c9f9 + 1028f8e commit e6bd9d0

File tree

8 files changed

+144
-22
lines changed

8 files changed

+144
-22
lines changed

docs/Config.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ git:
354354
branchLogCmd: git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --
355355

356356
# Commands used to display git log of all branches in the main window, they will be cycled in order of appearance (array of strings)
357-
allBranchesLogCmds: []
357+
allBranchesLogCmds:
358+
- git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium
358359

359360
# If true, do not spawn a separate process when using GPG
360361
overrideGpg: false

pkg/commands/git_commands/branch.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,7 @@ func (self *BranchCommands) Merge(branchName string, opts MergeOpts) error {
257257

258258
func (self *BranchCommands) AllBranchesLogCmdObj() *oscommands.CmdObj {
259259
// Only choose between non-empty, non-identical commands
260-
candidates := lo.Uniq(lo.WithoutEmpty(append([]string{
261-
self.UserConfig().Git.AllBranchesLogCmd,
262-
},
263-
self.UserConfig().Git.AllBranchesLogCmds...,
264-
)))
260+
candidates := lo.Uniq(lo.WithoutEmpty(self.UserConfig().Git.AllBranchesLogCmds))
265261

266262
n := len(candidates)
267263

pkg/config/app_config.go

+45
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package config
22

33
import (
4+
"errors"
45
"fmt"
56
"log"
67
"os"
@@ -10,6 +11,7 @@ import (
1011
"time"
1112

1213
"github.com/adrg/xdg"
14+
"github.com/jesseduffield/lazygit/pkg/utils"
1315
"github.com/jesseduffield/lazygit/pkg/utils/yaml_utils"
1416
"github.com/samber/lo"
1517
"gopkg.in/yaml.v3"
@@ -286,6 +288,11 @@ func computeMigratedConfig(path string, content []byte) ([]byte, error) {
286288
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
287289
}
288290

291+
err = migrateAllBranchesLogCmd(&rootNode)
292+
if err != nil {
293+
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err)
294+
}
295+
289296
// Add more migrations here...
290297

291298
if !reflect.DeepEqual(rootNode, originalCopy) {
@@ -386,6 +393,44 @@ func changeCustomCommandStreamAndOutputToOutputEnum(rootNode *yaml.Node) error {
386393
})
387394
}
388395

396+
// This migration is special because users have already defined
397+
// a single element at `allBranchesLogCmd` and the sequence at `allBranchesLogCmds`.
398+
// Some users have explicitly set `allBranchesLogCmd` to be an empty string in order
399+
// to remove it, so in that case we just delete the element, and add nothing to the list
400+
func migrateAllBranchesLogCmd(rootNode *yaml.Node) error {
401+
return yaml_utils.TransformNode(rootNode, []string{"git"}, func(gitNode *yaml.Node) error {
402+
cmdKeyNode, cmdValueNode := yaml_utils.LookupKey(gitNode, "allBranchesLogCmd")
403+
// Nothing to do if they do not have the deprecated item
404+
if cmdKeyNode == nil {
405+
return nil
406+
}
407+
408+
cmdsKeyNode, cmdsValueNode := yaml_utils.LookupKey(gitNode, "allBranchesLogCmds")
409+
if cmdsKeyNode == nil {
410+
// Create empty sequence node and attach it onto the root git node
411+
// We will later populate it with the individual allBranchesLogCmd record
412+
cmdsKeyNode = &yaml.Node{Kind: yaml.ScalarNode, Value: "allBranchesLogCmds"}
413+
cmdsValueNode = &yaml.Node{Kind: yaml.SequenceNode, Content: []*yaml.Node{}}
414+
gitNode.Content = append(gitNode.Content,
415+
cmdsKeyNode,
416+
cmdsValueNode,
417+
)
418+
} else if cmdsValueNode.Kind != yaml.SequenceNode {
419+
return errors.New("You should have an allBranchesLogCmds defined as a sequence!")
420+
}
421+
422+
if cmdValueNode.Value != "" {
423+
// Prepending the individual element to make it show up first in the list, which was prior behavior
424+
cmdsValueNode.Content = utils.Prepend(cmdsValueNode.Content, &yaml.Node{Kind: yaml.ScalarNode, Value: cmdValueNode.Value})
425+
}
426+
427+
// Clear out the existing allBranchesLogCmd, now that we have migrated it into the list
428+
_, _ = yaml_utils.RemoveKey(gitNode, "allBranchesLogCmd")
429+
430+
return nil
431+
})
432+
}
433+
389434
func (c *AppConfig) GetDebug() bool {
390435
return c.debug
391436
}

pkg/config/app_config_test.go

+86
Original file line numberDiff line numberDiff line change
@@ -781,3 +781,89 @@ func BenchmarkMigrationOnLargeConfiguration(b *testing.B) {
781781
_, _ = computeMigratedConfig("path doesn't matter", largeConfiguration)
782782
}
783783
}
784+
785+
func TestAllBranchesLogCmdMigrations(t *testing.T) {
786+
scenarios := []struct {
787+
name string
788+
input string
789+
expected string
790+
}{
791+
{
792+
name: "Incomplete Configuration Passes uneventfully",
793+
input: "git:",
794+
expected: "git:",
795+
}, {
796+
name: "Single Cmd with no Cmds",
797+
input: `git:
798+
allBranchesLogCmd: git log --graph --oneline
799+
`,
800+
expected: `git:
801+
allBranchesLogCmds:
802+
- git log --graph --oneline
803+
`,
804+
}, {
805+
name: "Cmd with one existing Cmds",
806+
input: `git:
807+
allBranchesLogCmd: git log --graph --oneline
808+
allBranchesLogCmds:
809+
- git log --graph --oneline --pretty
810+
`,
811+
expected: `git:
812+
allBranchesLogCmds:
813+
- git log --graph --oneline
814+
- git log --graph --oneline --pretty
815+
`,
816+
}, {
817+
name: "Only Cmds set have no changes",
818+
input: `git:
819+
allBranchesLogCmds:
820+
- git log
821+
`,
822+
expected: `git:
823+
allBranchesLogCmds:
824+
- git log
825+
`,
826+
}, {
827+
name: "Removes Empty Cmd When at end of yaml",
828+
input: `git:
829+
allBranchesLogCmds:
830+
- git log --graph --oneline
831+
allBranchesLogCmd:
832+
`,
833+
expected: `git:
834+
allBranchesLogCmds:
835+
- git log --graph --oneline
836+
`,
837+
}, {
838+
name: "Migrates when sequence defined inline",
839+
input: `git:
840+
allBranchesLogCmds: [foo, bar]
841+
allBranchesLogCmd: baz
842+
`,
843+
expected: `git:
844+
allBranchesLogCmds: [baz, foo, bar]
845+
`,
846+
}, {
847+
name: "Removes Empty Cmd With Keys Afterwards",
848+
input: `git:
849+
allBranchesLogCmds:
850+
- git log --graph --oneline
851+
allBranchesLogCmd:
852+
foo: bar
853+
`,
854+
expected: `git:
855+
allBranchesLogCmds:
856+
- git log --graph --oneline
857+
foo: bar
858+
`,
859+
},
860+
}
861+
862+
for _, s := range scenarios {
863+
t.Run(s.name, func(t *testing.T) {
864+
actual, err := computeMigratedConfig("path doesn't matter", []byte(s.input))
865+
assert.NoError(t, err)
866+
assert.Equal(t, s.expected, string(actual))
867+
})
868+
}
869+
}

pkg/config/user_config.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,6 @@ type GitConfig struct {
256256
AutoStageResolvedConflicts bool `yaml:"autoStageResolvedConflicts"`
257257
// Command used when displaying the current branch git log in the main window
258258
BranchLogCmd string `yaml:"branchLogCmd"`
259-
// Command used to display git log of all branches in the main window.
260-
// Deprecated: Use `allBranchesLogCmds` instead.
261-
AllBranchesLogCmd string `yaml:"allBranchesLogCmd" jsonschema:"deprecated"`
262259
// Commands used to display git log of all branches in the main window, they will be cycled in order of appearance (array of strings)
263260
AllBranchesLogCmds []string `yaml:"allBranchesLogCmds"`
264261
// If true, do not spawn a separate process when using GPG
@@ -823,7 +820,7 @@ func GetDefaultConfig() *UserConfig {
823820
FetchAll: true,
824821
AutoStageResolvedConflicts: true,
825822
BranchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --",
826-
AllBranchesLogCmd: "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium",
823+
AllBranchesLogCmds: []string{"git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium"},
827824
DisableForcePushing: false,
828825
CommitPrefixes: map[string][]CommitPrefixConfig(nil),
829826
BranchPrefix: "",

pkg/integration/tests/status/log_cmd.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ var LogCmd = NewIntegrationTest(NewIntegrationTestArgs{
1010
ExtraCmdArgs: []string{},
1111
Skip: false,
1212
SetupConfig: func(config *config.AppConfig) {
13-
config.GetUserConfig().Git.AllBranchesLogCmd = `echo "view1"`
14-
config.GetUserConfig().Git.AllBranchesLogCmds = []string{`echo "view2"`}
13+
config.GetUserConfig().Git.AllBranchesLogCmds = []string{`echo "view1"`, `echo "view2"`}
1514
},
1615
SetupRepo: func(shell *Shell) {},
1716
Run: func(t *TestDriver, keys config.KeybindingConfig) {

pkg/utils/yaml_utils/yaml_utils.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"gopkg.in/yaml.v3"
1010
)
1111

12-
func lookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) {
12+
func LookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) {
1313
for i := 0; i < len(node.Content)-1; i += 2 {
1414
if node.Content[i].Value == key {
1515
return node.Content[i], node.Content[i+1]
@@ -55,7 +55,7 @@ func transformNode(node *yaml.Node, path []string, transform func(node *yaml.Nod
5555
return transform(node)
5656
}
5757

58-
keyNode, valueNode := lookupKey(node, path[0])
58+
keyNode, valueNode := LookupKey(node, path[0])
5959
if keyNode == nil {
6060
return nil
6161
}
@@ -86,15 +86,15 @@ func renameYamlKey(node *yaml.Node, path []string, newKey string) error {
8686
return errors.New("yaml node in path is not a dictionary")
8787
}
8888

89-
keyNode, valueNode := lookupKey(node, path[0])
89+
keyNode, valueNode := LookupKey(node, path[0])
9090
if keyNode == nil {
9191
return nil
9292
}
9393

9494
// end of path reached: rename key
9595
if len(path) == 1 {
9696
// Check that new key doesn't exist yet
97-
if newKeyNode, _ := lookupKey(node, newKey); newKeyNode != nil {
97+
if newKeyNode, _ := LookupKey(node, newKey); newKeyNode != nil {
9898
return fmt.Errorf("new key `%s' already exists", newKey)
9999
}
100100

schema/config.json

+4-6
Original file line numberDiff line numberDiff line change
@@ -349,17 +349,15 @@
349349
"description": "Command used when displaying the current branch git log in the main window",
350350
"default": "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --"
351351
},
352-
"allBranchesLogCmd": {
353-
"type": "string",
354-
"description": "Command used to display git log of all branches in the main window.\nDeprecated: Use `allBranchesLogCmds` instead.",
355-
"default": "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium"
356-
},
357352
"allBranchesLogCmds": {
358353
"items": {
359354
"type": "string"
360355
},
361356
"type": "array",
362-
"description": "Commands used to display git log of all branches in the main window, they will be cycled in order of appearance (array of strings)"
357+
"description": "Commands used to display git log of all branches in the main window, they will be cycled in order of appearance (array of strings)",
358+
"default": [
359+
"git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium"
360+
]
363361
},
364362
"overrideGpg": {
365363
"type": "boolean",

0 commit comments

Comments
 (0)