diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index dde4b5382..8205f7ef6 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -310,6 +310,11 @@ func computeMigratedConfig(path string, content []byte, changes *ChangesSet) ([] return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) } + err = migratePagers(&rootNode, changes) + if err != nil { + return nil, false, fmt.Errorf("Couldn't migrate config file at `%s`: %w", path, err) + } + // Add more migrations here... if reflect.DeepEqual(rootNode, originalCopy) { @@ -469,6 +474,37 @@ func migrateAllBranchesLogCmd(rootNode *yaml.Node, changes *ChangesSet) error { }) } +func migratePagers(rootNode *yaml.Node, changes *ChangesSet) error { + return yaml_utils.TransformNode(rootNode, []string{"git"}, func(gitNode *yaml.Node) error { + pagingKeyNode, pagingValueNode := yaml_utils.LookupKey(gitNode, "paging") + if pagingKeyNode == nil || pagingValueNode.Kind != yaml.MappingNode { + // If there's no "paging" section (or it's not an object), there's nothing to do + return nil + } + + pagersKeyNode, _ := yaml_utils.LookupKey(gitNode, "pagers") + if pagersKeyNode != nil { + // Conversely, if there *is* already a "pagers" array, we also have nothing to do. + // This covers the case where the user keeps both the "paging" section and the "pagers" + // array for the sake of easier testing of old versions. + return nil + } + + pagingKeyNode.Value = "pagers" + pagingContentCopy := pagingValueNode.Content + pagingValueNode.Kind = yaml.SequenceNode + pagingValueNode.Tag = "!!seq" + pagingValueNode.Content = []*yaml.Node{{ + Kind: yaml.MappingNode, + Content: pagingContentCopy, + }} + + changes.Add("Moved git.paging object to git.pagers array") + + return nil + }) +} + func (c *AppConfig) GetDebug() bool { return c.debug } diff --git a/pkg/config/app_config_test.go b/pkg/config/app_config_test.go index cc7ffea79..1109256a9 100644 --- a/pkg/config/app_config_test.go +++ b/pkg/config/app_config_test.go @@ -1089,3 +1089,98 @@ func TestAllBranchesLogCmdMigrations(t *testing.T) { }) } } + +func TestPagerMigration(t *testing.T) { + scenarios := []struct { + name string + input string + expected string + expectedDidChange bool + expectedChanges []string + }{ + { + name: "Incomplete Configuration Passes uneventfully", + input: "git:", + expectedDidChange: false, + expectedChanges: []string{}, + }, + { + name: "No paging section", + input: `git: + autoFetch: true +`, + expected: `git: + autoFetch: true +`, + expectedDidChange: false, + expectedChanges: []string{}, + }, + { + name: "Both paging and pagers exist", + input: `git: + paging: + pager: delta --dark --paging=never + pagers: + - diff: diff-so-fancy +`, + expected: `git: + paging: + pager: delta --dark --paging=never + pagers: + - diff: diff-so-fancy +`, + expectedDidChange: false, + expectedChanges: []string{}, + }, + { + name: "paging is not an object", + input: `git: + paging: 5 +`, + expected: `git: + paging: 5 +`, + expectedDidChange: false, + expectedChanges: []string{}, + }, + { + name: "paging is moved to pagers array (keeping the order)", + input: `git: + paging: + pager: delta --dark --paging=never + autoFetch: true +`, + expected: `git: + pagers: + - pager: delta --dark --paging=never + autoFetch: true +`, + expectedDidChange: true, + expectedChanges: []string{"Moved git.paging object to git.pagers array"}, + }, + { + name: "paging is moved to pagers array even if empty", + input: `git: + paging: {} +`, + expected: `git: + pagers: [{}] +`, + expectedDidChange: true, + expectedChanges: []string{"Moved git.paging object to git.pagers array"}, + }, + } + + for _, s := range scenarios { + t.Run(s.name, func(t *testing.T) { + changes := NewChangesSet() + actual, didChange, err := computeMigratedConfig("path doesn't matter", []byte(s.input), changes) + assert.NoError(t, err) + assert.Equal(t, s.expectedDidChange, didChange) + if didChange { + assert.Equal(t, s.expected, string(actual)) + } + assert.Equal(t, s.expectedChanges, changes.ToSliceFromOldest()) + }) + } +}