refactor(git): move deprecated functions

This commit is contained in:
Jan De Dobbeleer 2021-10-31 21:10:18 +01:00 committed by Jan De Dobbeleer
parent 3f8400e8f1
commit 42f18697fd
5 changed files with 388 additions and 448 deletions

View file

@ -77,7 +77,7 @@ func (s *GitStatus) String() string {
status += stringIfValue(s.Modified, "~")
status += stringIfValue(s.Deleted, "-")
status += stringIfValue(s.Unmerged, "x")
return status
return strings.TrimSpace(status)
}
type git struct {
@ -98,6 +98,8 @@ const (
// DisplayUpstreamIcon show or hide the upstream icon
DisplayUpstreamIcon Property = "display_upstream_icon"
// BranchMaxLength truncates the length of the branch name
BranchMaxLength Property = "branch_max_length"
// BranchIcon the icon to use as branch indicator
BranchIcon Property = "branch_icon"
// BranchIdenticalIcon the icon to display when the remote and local branch are identical
@ -120,10 +122,6 @@ const (
NoCommitsIcon Property = "no_commits_icon"
// TagIcon shows before the tag context
TagIcon Property = "tag_icon"
// StashCountIcon shows before the stash context
StashCountIcon Property = "stash_count_icon"
// StatusSeparatorIcon shows between staging and working area
StatusSeparatorIcon Property = "status_separator_icon"
// MergeIcon shows before the merge context
MergeIcon Property = "merge_icon"
// GithubIcon shows√ when upstream is github
@ -198,9 +196,6 @@ func (g *git) string() string {
if displayStatus || statusColorsEnabled {
g.setGitStatus()
}
if statusColorsEnabled {
g.SetStatusColor()
}
if g.repo.Upstream != "" && g.props.getBool(DisplayUpstreamIcon, false) {
g.repo.UpstreamIcon = g.getUpstreamIcon()
}
@ -214,7 +209,7 @@ func (g *git) string() string {
}
// legacy render string if no template
// remove this for 6.0
return g.renderDeprecatedString()
return g.renderDeprecatedString(statusColorsEnabled)
}
func (g *git) templateString(segmentTemplate string) string {
@ -254,25 +249,6 @@ func (g *git) getBranchStatus() string {
return ""
}
func (g *git) getStatusDetailString(status *GitStatus, color, icon Property, defaultIcon string) string {
prefix := g.props.getString(icon, defaultIcon)
foregroundColor := g.props.getColor(color, g.props.foreground)
if !g.props.getBool(DisplayStatusDetail, true) {
return g.colorStatusString(prefix, "", foregroundColor)
}
return g.colorStatusString(prefix, status.String(), foregroundColor)
}
func (g *git) colorStatusString(prefix, status, color string) string {
if color == g.props.foreground {
return fmt.Sprintf("%s%s", prefix, status)
}
if strings.Contains(prefix, "</>") {
return fmt.Sprintf("%s<%s>%s</>", prefix, color, status)
}
return fmt.Sprintf("<%s>%s%s</>", color, prefix, status)
}
func (g *git) getUpstreamIcon() string {
upstream := replaceAllString("/.*", g.repo.Upstream, "")
url := g.getOriginURL(upstream)
@ -313,27 +289,6 @@ func (g *git) setGitStatus() {
}
}
func (g *git) SetStatusColor() {
if g.props.getBool(ColorBackground, true) {
g.props.background = g.getStatusColor(g.props.background)
} else {
g.props.foreground = g.getStatusColor(g.props.foreground)
}
}
func (g *git) getStatusColor(defaultValue string) string {
if g.repo.Staging.Changed || g.repo.Working.Changed {
return g.props.getColor(LocalChangesColor, defaultValue)
} else if g.repo.Ahead > 0 && g.repo.Behind > 0 {
return g.props.getColor(AheadAndBehindColor, defaultValue)
} else if g.repo.Ahead > 0 {
return g.props.getColor(AheadColor, defaultValue)
} else if g.repo.Behind > 0 {
return g.props.getColor(BehindColor, defaultValue)
}
return defaultValue
}
func (g *git) getGitCommand() string {
inWSLSharedDrive := func(env environmentInfo) bool {
return env.isWsl() && strings.HasPrefix(env.getcwd(), "/mnt/")

View file

@ -3,6 +3,7 @@ package main
import (
"bytes"
"fmt"
"strings"
)
const (
@ -26,13 +27,18 @@ const (
BehindColor Property = "behind_color"
// AheadColor if set, the color to use when the branch is ahead and behind the remote
AheadColor Property = "ahead_color"
// BranchMaxLength truncates the length of the branch name
BranchMaxLength Property = "branch_max_length"
// WorktreeCountIcon shows before the worktree context
WorktreeCountIcon Property = "worktree_count_icon"
// StashCountIcon shows before the stash context
StashCountIcon Property = "stash_count_icon"
// StatusSeparatorIcon shows between staging and working area
StatusSeparatorIcon Property = "status_separator_icon"
)
func (g *git) renderDeprecatedString() string {
func (g *git) renderDeprecatedString(statusColorsEnabled bool) string {
if statusColorsEnabled {
g.SetStatusColor()
}
buffer := new(bytes.Buffer)
// remote (if available)
if len(g.repo.UpstreamIcon) != 0 {
@ -60,3 +66,49 @@ func (g *git) renderDeprecatedString() string {
}
return buffer.String()
}
func (g *git) SetStatusColor() {
if g.props.getBool(ColorBackground, true) {
g.props.background = g.getStatusColor(g.props.background)
} else {
g.props.foreground = g.getStatusColor(g.props.foreground)
}
}
func (g *git) getStatusColor(defaultValue string) string {
if g.repo.Staging.Changed || g.repo.Working.Changed {
return g.props.getColor(LocalChangesColor, defaultValue)
} else if g.repo.Ahead > 0 && g.repo.Behind > 0 {
return g.props.getColor(AheadAndBehindColor, defaultValue)
} else if g.repo.Ahead > 0 {
return g.props.getColor(AheadColor, defaultValue)
} else if g.repo.Behind > 0 {
return g.props.getColor(BehindColor, defaultValue)
}
return defaultValue
}
func (g *git) getStatusDetailString(status *GitStatus, color, icon Property, defaultIcon string) string {
prefix := g.props.getString(icon, defaultIcon)
foregroundColor := g.props.getColor(color, g.props.foreground)
if !g.props.getBool(DisplayStatusDetail, true) {
return g.colorStatusString(prefix, "", foregroundColor)
}
return g.colorStatusString(prefix, status.String(), foregroundColor)
}
func (g *git) colorStatusString(prefix, status, color string) string {
if color == g.props.foreground && len(status) == 0 {
return prefix
}
if color == g.props.foreground {
return fmt.Sprintf("%s %s", prefix, status)
}
if strings.Contains(prefix, "</>") {
return fmt.Sprintf("%s <%s>%s</>", prefix, color, status)
}
if len(status) == 0 {
return fmt.Sprintf("<%s>%s</>", color, prefix)
}
return fmt.Sprintf("<%s>%s %s</>", color, prefix, status)
}

View file

@ -0,0 +1,283 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetStatusDetailStringDefault(t *testing.T) {
expected := "icon +1"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverride(t *testing.T) {
expected := "<#123456>icon +1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverrideAndIconColorOverride(t *testing.T) {
expected := "<#789123>work</> <#123456>+1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
LocalWorkingIcon: "<#789123>work</>",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverrideNoIconColorOverride(t *testing.T) {
expected := "<#123456>work +1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
LocalWorkingIcon: "work",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringNoStatus(t *testing.T) {
expected := "icon"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
DisplayStatusDetail: false,
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringNoStatusColorOverride(t *testing.T) {
expected := "<#123456>icon</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
DisplayStatusDetail: false,
WorkingColor: "#123456",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusColorLocalChangesStaging(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorLocalChangesWorking(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorAheadAndBehind(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 1,
Behind: 3,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadAndBehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorAhead(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 1,
Behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorBehind(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 0,
Behind: 5,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorDefault(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 0,
Behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: changesColor,
},
},
}
assert.Equal(t, expected, g.getStatusColor(expected))
}
func TestSetStatusColorForeground(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: changesColor,
ColorBackground: false,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.foreground)
}
func TestSetStatusColorBackground(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: changesColor,
ColorBackground: true,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.background)
}
func TestStatusColorsWithoutDisplayStatus(t *testing.T) {
expected := changesColor
context := &detachedContext{
status: "## main...origin/main [ahead 33]\n M myfile",
}
g := setupHEADContextEnv(context)
g.props = &properties{
values: map[Property]interface{}{
DisplayStatus: false,
StatusColorsEnabled: true,
LocalChangesColor: expected,
},
}
g.string()
assert.Equal(t, expected, g.props.background)
}

View file

@ -538,10 +538,23 @@ func TestParseGitStatsInvalidLine(t *testing.T) {
assert.False(t, status.Changed)
}
func bootstrapUpstreamTest(upstream string) *git {
func TestGitUpstream(t *testing.T) {
cases := []struct {
Case string
Expected string
Upstream string
}{
{Case: "GitHub", Expected: "GH", Upstream: "github.com/test"},
{Case: "Gitlab", Expected: "GL", Upstream: "gitlab.com/test"},
{Case: "Bitbucket", Expected: "BB", Upstream: "bitbucket.org/test"},
{Case: "Azure DevOps", Expected: "AD", Upstream: "dev.azure.com/test"},
{Case: "Azure DevOps Dos", Expected: "AD", Upstream: "test.visualstudio.com"},
{Case: "Gitstash", Expected: "G", Upstream: "gitstash.com/test"},
}
for _, tc := range cases {
env := &MockedEnvironment{}
env.On("isWsl", nil).Return(false)
env.On("runCommand", "git", []string{"--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false", "remote", "get-url", "origin"}).Return(upstream, nil)
env.On("runCommand", "git", []string{"--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false", "remote", "get-url", "origin"}).Return(tc.Upstream, nil)
env.On("getRuntimeGOOS", nil).Return("unix")
props := &properties{
values: map[Property]interface{}{
@ -559,317 +572,9 @@ func bootstrapUpstreamTest(upstream string) *git {
},
props: props,
}
return g
}
func TestGetUpstreamSymbolGitHub(t *testing.T) {
g := bootstrapUpstreamTest("github.com/test")
upstreamIcon := g.getUpstreamIcon()
assert.Equal(t, "GH", upstreamIcon)
assert.Equal(t, tc.Expected, upstreamIcon, tc.Case)
}
func TestGetUpstreamSymbolGitLab(t *testing.T) {
g := bootstrapUpstreamTest("gitlab.com/test")
upstreamIcon := g.getUpstreamIcon()
assert.Equal(t, "GL", upstreamIcon)
}
func TestGetUpstreamSymbolBitBucket(t *testing.T) {
g := bootstrapUpstreamTest("bitbucket.org/test")
upstreamIcon := g.getUpstreamIcon()
assert.Equal(t, "BB", upstreamIcon)
}
func TestGetUpstreamSymbolAzureDevOps(t *testing.T) {
g := bootstrapUpstreamTest("dev.azure.com/test")
upstreamIcon := g.getUpstreamIcon()
assert.Equal(t, "AD", upstreamIcon)
g = bootstrapUpstreamTest("test.visualstudio.com")
upstreamIcon = g.getUpstreamIcon()
assert.Equal(t, "AD", upstreamIcon)
}
func TestGetUpstreamSymbolGit(t *testing.T) {
g := bootstrapUpstreamTest("gitstash.com/test")
upstreamIcon := g.getUpstreamIcon()
assert.Equal(t, "G", upstreamIcon)
}
func TestGetStatusColorLocalChangesStaging(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorLocalChangesWorking(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorAheadAndBehind(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 1,
Behind: 3,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadAndBehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorAhead(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 1,
Behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorBehind(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 0,
Behind: 5,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}
func TestGetStatusColorDefault(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{},
Working: &GitStatus{},
Ahead: 0,
Behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: changesColor,
},
},
}
assert.Equal(t, expected, g.getStatusColor(expected))
}
func TestSetStatusColorForeground(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: changesColor,
ColorBackground: false,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.foreground)
}
func TestSetStatusColorBackground(t *testing.T) {
expected := changesColor
repo := &Repo{
Staging: &GitStatus{
Changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: changesColor,
ColorBackground: true,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.background)
}
func TestStatusColorsWithoutDisplayStatus(t *testing.T) {
expected := changesColor
context := &detachedContext{
status: "## main...origin/main [ahead 33]\n M myfile",
}
g := setupHEADContextEnv(context)
g.props = &properties{
values: map[Property]interface{}{
DisplayStatus: false,
StatusColorsEnabled: true,
LocalChangesColor: expected,
},
}
g.string()
assert.Equal(t, expected, g.props.background)
}
func TestGetStatusDetailStringDefault(t *testing.T) {
expected := "icon +1"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverride(t *testing.T) {
expected := "<#123456>icon +1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverrideAndIconColorOverride(t *testing.T) {
expected := "<#789123>work</><#123456> +1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
LocalWorkingIcon: "<#789123>work</>",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringDefaultColorOverrideNoIconColorOverride(t *testing.T) {
expected := "<#123456>work +1</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
WorkingColor: "#123456",
LocalWorkingIcon: "work",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringNoStatus(t *testing.T) {
expected := "icon"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
DisplayStatusDetail: false,
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetStatusDetailStringNoStatusColorOverride(t *testing.T) {
expected := "<#123456>icon</>"
status := &GitStatus{
Changed: true,
Added: 1,
}
g := &git{
props: &properties{
values: map[Property]interface{}{
DisplayStatusDetail: false,
WorkingColor: "#123456",
},
foreground: "#111111",
},
}
assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon"))
}
func TestGetBranchStatus(t *testing.T) {

View file

@ -512,6 +512,9 @@
"properties": {
"properties": {
"properties": {
"template": {
"$ref": "#/definitions/template"
},
"branch_icon": {
"type": "string",
"title": "Branch Icon",
@ -554,12 +557,6 @@
"description": "Display the local changes or not",
"default": true
},
"display_status_detail": {
"type": "boolean",
"title": "Display Status Detail",
"description": "Display the local changes in detail or not",
"default": true
},
"display_stash_count": {
"type": "boolean",
"title": "Display Stash Count",
@ -572,36 +569,6 @@
"description": "Display the worktree count or not",
"default": false
},
"status_separator_icon": {
"type": "string",
"title": "Status Separator Icon",
"description": "Icon/text to display between staging and working area changes",
"default": " | "
},
"local_working_icon": {
"type": "string",
"title": "Local Working Icon",
"description": "The icon to display in front of the working area changes",
"default": "\uF044"
},
"local_staged_icon": {
"type": "string",
"title": "Local Staged Icon",
"description": "The icon to display in front of the staged area changes",
"default": "\uF046"
},
"stash_count_icon": {
"type": "string",
"title": "Stash Count Icon",
"description": "The icon to display before the stash context",
"default": "\uF692 "
},
"worktree_count_icon": {
"type": "string",
"title": "Worktree Count Icon",
"description": "The icon to display before the worktree context",
"default": "\uF1bb "
},
"commit_icon": {
"type": "string",
"title": "Commit Icon",
@ -680,28 +647,6 @@
"description": "Icon/text to display when the upstream is not known/mapped",
"default": "\uE5FB"
},
"working_color": { "$ref": "#/definitions/color" },
"staging_color": { "$ref": "#/definitions/color" },
"status_colors_enabled": {
"type": "boolean",
"title": "Status Colors Enabled",
"description": "Color the segment based on the repository status",
"default": false
},
"color_background": {
"type": "boolean",
"title": "Color Background",
"description": "Color the background or foreground",
"default": true
},
"local_changes_color": {
"$ref": "#/definitions/color"
},
"ahead_and_behind_color": {
"$ref": "#/definitions/color"
},
"behind_color": { "$ref": "#/definitions/color" },
"ahead_color": { "$ref": "#/definitions/color" },
"branch_max_length": {
"type": "integer",
"title": "Branch max length",