-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Migrate deprecated AllBranchesLogCmd to AllBranchesLogCmds #4345
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -281,6 +281,11 @@ func computeMigratedConfig(path string, content []byte) ([]byte, error) { | |
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) | ||
} | ||
|
||
err = migrateAllBranchesLogCmd(&rootNode) | ||
if err != nil { | ||
return nil, fmt.Errorf("Couldn't migrate config file at `%s`: %s", path, err) | ||
} | ||
|
||
// Add more migrations here... | ||
|
||
if !reflect.DeepEqual(rootNode, originalCopy) { | ||
|
@@ -341,6 +346,44 @@ func changeCommitPrefixesMap(rootNode *yaml.Node) error { | |
}) | ||
} | ||
|
||
// This migration is special because users have already defined | ||
// a single element at `allBranchesLogCmd` and the sequence at `allBranchesLogCmds`. | ||
// Some users have explicitly set `allBranchesLogCmd` to be an empty string in order | ||
// to remove it, so in that case we just delete the element, and add nothing to the list | ||
func migrateAllBranchesLogCmd(rootNode *yaml.Node) error { | ||
return yaml_utils.TransformNode(rootNode, []string{"git"}, func(gitNode *yaml.Node) error { | ||
cmdKeyNode, cmdValueNode := yaml_utils.LookupKey(gitNode, "allBranchesLogCmd") | ||
// Nothing to do if they do not have the deprecated item | ||
if cmdKeyNode == nil { | ||
return nil | ||
} | ||
|
||
cmdsKeyNode, cmdsValueNode := yaml_utils.LookupKey(gitNode, "allBranchesLogCmds") | ||
if cmdsKeyNode == nil { | ||
// Create dummy node and attach it onto the root git node | ||
cmdsKeyNode = &yaml.Node{Kind: yaml.ScalarNode, Value: "allBranchesLogCmds"} | ||
cmdsValueNode = &yaml.Node{Kind: yaml.SequenceNode, Content: []*yaml.Node{}} | ||
gitNode.Content = append(gitNode.Content, | ||
cmdsKeyNode, | ||
cmdsValueNode, | ||
) | ||
} | ||
|
||
if cmdValueNode.Value != "" { | ||
if cmdsValueNode.Kind != yaml.SequenceNode { | ||
return fmt.Errorf("You should have an allBranchesLogCmds defined as a sequence!") | ||
} | ||
Comment on lines
+373
to
+375
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it slightly confusing to do this here, where in half of the cases we have just created this ourselves and know it's the right type. I would move this up to an |
||
// Prepending the individual element to make it show up first in the list, which was prior behavior | ||
cmdsValueNode.Content = append([]*yaml.Node{{Kind: yaml.ScalarNode, Value: cmdValueNode.Value}}, cmdsValueNode.Content...) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have |
||
} | ||
|
||
// Clear out the existing allBranchesLogCmd, now that we have migrated it into the list | ||
_, _ = yaml_utils.RemoveKey(gitNode, "allBranchesLogCmd") | ||
|
||
return nil | ||
}) | ||
} | ||
|
||
func (c *AppConfig) GetDebug() bool { | ||
return c.debug | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -695,3 +695,82 @@ func BenchmarkMigrationOnLargeConfiguration(b *testing.B) { | |
_, _ = computeMigratedConfig("path doesn't matter", largeConfiguration) | ||
} | ||
} | ||
|
||
func TestAllBranchesLogCmdMigrations(t *testing.T) { | ||
scenarios := []struct { | ||
name string | ||
input string | ||
expected string | ||
}{ | ||
{ | ||
name: "Incomplete Configuration Passes uneventfully", | ||
input: "git:", | ||
expected: "git:", | ||
}, { | ||
name: "Single Cmd with no Cmds", | ||
input: `git: | ||
allBranchesLogCmd: git log --graph --oneline | ||
`, | ||
expected: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
`, | ||
}, { | ||
name: "Cmd with one existing Cmds", | ||
input: `git: | ||
allBranchesLogCmd: git log --graph --oneline | ||
allBranchesLogCmds: | ||
- git log --graph --oneline --pretty | ||
`, | ||
expected: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
- git log --graph --oneline --pretty | ||
`, | ||
}, { | ||
name: "Only Cmds set have no changes", | ||
input: `git: | ||
allBranchesLogCmds: | ||
- git log | ||
`, | ||
expected: `git: | ||
allBranchesLogCmds: | ||
- git log | ||
`, | ||
}, { | ||
name: "Removes Empty Cmd When at end of yaml", | ||
input: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
allBranchesLogCmd: | ||
`, | ||
expected: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
`, | ||
}, { | ||
name: "Removes Empty Cmd With Keys Afterwards", | ||
input: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
allBranchesLogCmd: | ||
foo: bar | ||
`, | ||
expected: `git: | ||
allBranchesLogCmds: | ||
- git log --graph --oneline | ||
foo: bar | ||
`, | ||
}, | ||
} | ||
|
||
for _, s := range scenarios { | ||
t.Run(s.name, func(t *testing.T) { | ||
actual, err := computeMigratedConfig("path doesn't matter", []byte(s.input)) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
Comment on lines
+770
to
+772
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's |
||
assert.Equal(t, s.expected, string(actual)) | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,7 +61,7 @@ func updateYamlNode(node *yaml.Node, path []string, value string) (bool, error) | |
} | ||
|
||
key := path[0] | ||
if _, valueNode := lookupKey(node, key); valueNode != nil { | ||
if _, valueNode := LookupKey(node, key); valueNode != nil { | ||
return updateYamlNode(valueNode, path[1:], value) | ||
} | ||
|
||
|
@@ -90,7 +90,7 @@ func updateYamlNode(node *yaml.Node, path []string, value string) (bool, error) | |
return updateYamlNode(newNode, path[1:], value) | ||
} | ||
|
||
func lookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) { | ||
func LookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) { | ||
for i := 0; i < len(node.Content)-1; i += 2 { | ||
if node.Content[i].Value == key { | ||
return node.Content[i], node.Content[i+1] | ||
|
@@ -100,6 +100,19 @@ func lookupKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) { | |
return nil, nil | ||
} | ||
|
||
// Returns the key and value if they were present | ||
func RemoveKey(node *yaml.Node, key string) (*yaml.Node, *yaml.Node) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would make sense to add a test for this, we have tests for most other things in yaml_utils. |
||
for i := 0; i < len(node.Content)-1; i += 2 { | ||
if node.Content[i].Value == key { | ||
key, value := node.Content[i], node.Content[i+1] | ||
node.Content = append(node.Content[:i], node.Content[i+2:]...) | ||
return key, value | ||
} | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
// Walks a yaml document from the root node to the specified path, and then applies the transformation to that node. | ||
// If the requested path is not defined in the document, no changes are made to the document. | ||
func TransformNode(rootNode *yaml.Node, path []string, transform func(node *yaml.Node) error) error { | ||
|
@@ -123,7 +136,7 @@ func transformNode(node *yaml.Node, path []string, transform func(node *yaml.Nod | |
return transform(node) | ||
} | ||
|
||
keyNode, valueNode := lookupKey(node, path[0]) | ||
keyNode, valueNode := LookupKey(node, path[0]) | ||
if keyNode == nil { | ||
return nil | ||
} | ||
|
@@ -154,15 +167,15 @@ func renameYamlKey(node *yaml.Node, path []string, newKey string) error { | |
return errors.New("yaml node in path is not a dictionary") | ||
} | ||
|
||
keyNode, valueNode := lookupKey(node, path[0]) | ||
keyNode, valueNode := LookupKey(node, path[0]) | ||
if keyNode == nil { | ||
return nil | ||
} | ||
|
||
// end of path reached: rename key | ||
if len(path) == 1 { | ||
// Check that new key doesn't exist yet | ||
if newKeyNode, _ := lookupKey(node, newKey); newKeyNode != nil { | ||
if newKeyNode, _ := LookupKey(node, newKey); newKeyNode != nil { | ||
return fmt.Errorf("new key `%s' already exists", newKey) | ||
} | ||
|
||
|
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.
What's "dummy" about this? I find this comment more confusing than helpful, and I think we might just delete it.