mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-27 09:46:10 -04:00
Migrate gui.branchColors to gui.branchColorPatterns
gui.branchColors has been deprecated in favor of gui.branchColorPatterns since 0.44.0. We are about to move gui.branchColorPatterns into gui.theme, and the deprecated key would have to move along with it. Migrate it instead, so that we can remove it. gui.branchColors matched its keys against the part of a branch name before the first slash. The pattern ^<key>(/|$), with the key escaped, matches the same branches. If gui.branchColorPatterns is set, gui.branchColors has no effect; in that case the migration removes it. This check is done per file. So if the global config sets gui.branchColorPatterns and a repo config sets only gui.branchColors, the repo's colors were ignored so far, and now they apply. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5ed0345899
commit
573cd8a005
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -364,6 +365,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 = migrateBranchColors(&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) {
|
||||
@@ -630,6 +636,43 @@ func migratePagersToDiffRenderers(rootNode *yaml.Node, changes *ChangesSet) erro
|
||||
})
|
||||
}
|
||||
|
||||
// The deprecated gui.branchColors matched its keys against the part of a branch
|
||||
// name before the first slash. Turn each key into a pattern that matches the
|
||||
// same branches. If the file has a non-empty gui.branchColorPatterns,
|
||||
// gui.branchColors was ignored, so remove it.
|
||||
func migrateBranchColors(rootNode *yaml.Node, changes *ChangesSet) error {
|
||||
return yaml_utils.TransformNode(rootNode, []string{"gui"}, func(guiNode *yaml.Node) error {
|
||||
branchColorsKeyNode, branchColorsValueNode := yaml_utils.LookupKey(guiNode, "branchColors")
|
||||
if branchColorsKeyNode == nil || branchColorsValueNode.Kind != yaml.MappingNode {
|
||||
return nil
|
||||
}
|
||||
|
||||
patternsKeyNode, patternsValueNode := yaml_utils.LookupKey(guiNode, "branchColorPatterns")
|
||||
if patternsKeyNode != nil {
|
||||
switch {
|
||||
case patternsValueNode.Kind == yaml.MappingNode && len(patternsValueNode.Content) > 0:
|
||||
yaml_utils.RemoveKey(guiNode, "branchColors")
|
||||
changes.Add("Removed 'gui.branchColors'; it had no effect because 'gui.branchColorPatterns' is set")
|
||||
return nil
|
||||
case patternsValueNode.Kind == yaml.MappingNode || patternsValueNode.Tag == "!!null":
|
||||
yaml_utils.RemoveKey(guiNode, "branchColorPatterns")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
branchColorsKeyNode.Value = "branchColorPatterns"
|
||||
for i := 0; i < len(branchColorsValueNode.Content)-1; i += 2 {
|
||||
keyNode := branchColorsValueNode.Content[i]
|
||||
keyNode.Value = "^" + regexp.QuoteMeta(keyNode.Value) + "(/|$)"
|
||||
keyNode.Tag = "!!str"
|
||||
}
|
||||
changes.Add("Converted 'gui.branchColors' to 'gui.branchColorPatterns'")
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func hasNonNullScalarValue(node *yaml.Node) bool {
|
||||
return node != nil && node.Kind == yaml.ScalarNode && node.Tag != "!!null" && node.Value != ""
|
||||
}
|
||||
|
||||
@@ -821,3 +821,107 @@ func TestPagerMigration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchColorsMigration(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
expectedDidChange bool
|
||||
expectedChanges []string
|
||||
}{
|
||||
{
|
||||
name: "No branchColors",
|
||||
input: "gui:\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" '^docs/': blue\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "branchColors is not an object",
|
||||
input: "gui:\n" +
|
||||
" branchColors: 5\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
{
|
||||
name: "branchColors is converted to patterns in place",
|
||||
input: "gui:\n" +
|
||||
" scrollHeight: 2\n" +
|
||||
" branchColors:\n" +
|
||||
" feature: green\n" +
|
||||
" v1.x: '#ff0000'\n" +
|
||||
" 123: red\n" +
|
||||
" mouseEvents: false\n",
|
||||
expected: "gui:\n" +
|
||||
" scrollHeight: 2\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" ^feature(/|$): green\n" +
|
||||
" ^v1\\.x(/|$): '#ff0000'\n" +
|
||||
" ^123(/|$): red\n" +
|
||||
" mouseEvents: false\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Converted 'gui.branchColors' to 'gui.branchColorPatterns'"},
|
||||
},
|
||||
{
|
||||
name: "branchColors is removed if branchColorPatterns is set",
|
||||
input: "gui:\n" +
|
||||
" branchColors:\n" +
|
||||
" feature: green\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" '^docs/': blue\n",
|
||||
expected: "gui:\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" '^docs/': blue\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Removed 'gui.branchColors'; it had no effect because 'gui.branchColorPatterns' is set"},
|
||||
},
|
||||
{
|
||||
name: "branchColors replaces an empty branchColorPatterns",
|
||||
input: "gui:\n" +
|
||||
" branchColorPatterns: {}\n" +
|
||||
" branchColors:\n" +
|
||||
" feature: green\n",
|
||||
expected: "gui:\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" ^feature(/|$): green\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Converted 'gui.branchColors' to 'gui.branchColorPatterns'"},
|
||||
},
|
||||
{
|
||||
name: "branchColors replaces a null branchColorPatterns",
|
||||
input: "gui:\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" branchColors:\n" +
|
||||
" feature: green\n",
|
||||
expected: "gui:\n" +
|
||||
" branchColorPatterns:\n" +
|
||||
" ^feature(/|$): green\n",
|
||||
expectedDidChange: true,
|
||||
expectedChanges: []string{"Converted 'gui.branchColors' to 'gui.branchColorPatterns'"},
|
||||
},
|
||||
{
|
||||
name: "branchColors is kept if branchColorPatterns is not an object",
|
||||
input: "gui:\n" +
|
||||
" branchColorPatterns: 5\n" +
|
||||
" branchColors:\n" +
|
||||
" feature: green\n",
|
||||
expectedDidChange: false,
|
||||
expectedChanges: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
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())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +71,6 @@ type GuiConfig struct {
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-author-color
|
||||
AuthorColors map[string]string `yaml:"authorColors"`
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-branch-color
|
||||
// Deprecated: use branchColorPatterns instead
|
||||
BranchColors map[string]string `yaml:"branchColors" jsonschema:"deprecated"`
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-branch-color
|
||||
BranchColorPatterns map[string]string `yaml:"branchColorPatterns"`
|
||||
// Custom icons for filenames and file extensions
|
||||
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-files-icon--color
|
||||
|
||||
+1
-6
@@ -526,12 +526,7 @@ func (gui *Gui) onUserConfigLoaded() error {
|
||||
icons.SetNerdFontsVersion("")
|
||||
}
|
||||
|
||||
if len(userConfig.Gui.BranchColorPatterns) > 0 {
|
||||
presentation.SetCustomBranches(userConfig.Gui.BranchColorPatterns, true)
|
||||
} else {
|
||||
// Fall back to the deprecated branchColors config
|
||||
presentation.SetCustomBranches(userConfig.Gui.BranchColors, false)
|
||||
}
|
||||
presentation.SetCustomBranches(userConfig.Gui.BranchColorPatterns)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
|
||||
type colorMatcher struct {
|
||||
patterns map[string]*style.TextStyle
|
||||
isRegex bool // NOTE: this value is needed only until the deprecated branchColors config is removed and only regex color patterns are used
|
||||
}
|
||||
|
||||
var colorPatterns *colorMatcher
|
||||
@@ -201,17 +200,9 @@ func GetBranchTextStyle(name string) style.TextStyle {
|
||||
}
|
||||
|
||||
func (m *colorMatcher) match(name string) (*style.TextStyle, bool) {
|
||||
if m.isRegex {
|
||||
for pattern, style := range m.patterns {
|
||||
if matched, _ := regexp.MatchString(pattern, name); matched {
|
||||
return style, true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// old behavior using the deprecated branchColors behavior matching on branch type
|
||||
branchType := strings.Split(name, "/")[0]
|
||||
if value, ok := m.patterns[branchType]; ok {
|
||||
return value, true
|
||||
for pattern, style := range m.patterns {
|
||||
if matched, _ := regexp.MatchString(pattern, name); matched {
|
||||
return style, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,10 +262,9 @@ func divergenceStr(
|
||||
return result
|
||||
}
|
||||
|
||||
func SetCustomBranches(customBranchColors map[string]string, isRegex bool) {
|
||||
func SetCustomBranches(customBranchColors map[string]string) {
|
||||
colorPatterns = &colorMatcher{
|
||||
patterns: utils.SetCustomColors(customBranchColors),
|
||||
isRegex: isRegex,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -419,7 +419,7 @@ func Test_getBranchDisplayStrings(t *testing.T) {
|
||||
defer color.ForceSetColorLevel(oldColorLevel)
|
||||
|
||||
c := common.NewDummyCommon()
|
||||
SetCustomBranches(c.UserConfig().Gui.BranchColorPatterns, true)
|
||||
SetCustomBranches(c.UserConfig().Gui.BranchColorPatterns)
|
||||
|
||||
for i, s := range scenarios {
|
||||
icons.SetNerdFontsVersion(lo.Ternary(s.useIcons, "3", ""))
|
||||
|
||||
@@ -537,13 +537,6 @@
|
||||
"type": "object",
|
||||
"description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-author-color"
|
||||
},
|
||||
"branchColors": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object",
|
||||
"description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#custom-branch-color\nDeprecated: use branchColorPatterns instead"
|
||||
},
|
||||
"branchColorPatterns": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
|
||||
Reference in New Issue
Block a user