Skip to content
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

Allow multiple commit prefixes #4253

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,6 @@ git:
# If true, do not allow force pushes
disableForcePushing: false

# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix
commitPrefix:
# pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use "^\\w+\\/(\\w+-\\w+).*"
pattern: ""

# Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use "[$1] "
replace: ""

Comment on lines -344 to -351
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was automatically removed by go generate. I guess since the element is now a sequence instead of a mapping. Is there some way we can tag the field in the config struct definition so that these details continue to show here?

# See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-branch-name-prefix
branchPrefix: ""

Expand Down Expand Up @@ -931,20 +923,29 @@ Example:
```yaml
git:
commitPrefix:
pattern: "^\\w+\\/(\\w+-\\w+).*"
replace: '[$1] '
- pattern: "^\\w+\\/(\\w+-\\w+).*"
replace: '[$1] '
```

If you want repository-specific prefixes, you can map them with `commitPrefixes`. If you have both `commitPrefixes` defined and an entry in `commitPrefixes` for the current repo, the `commitPrefixes` entry is given higher precedence. Repository folder names must be an exact match.
If you want repository-specific prefixes, you can map them with `commitPrefixes`. If you have both entries in `commitPrefix` defined and an repository match in `commitPrefixes` for the current repo, the `commitPrefixes` entry is given higher precedence. Repository folder names must be an exact match.

```yaml
git:
commitPrefixes:
my_project: # This is repository folder name
pattern: "^\\w+\\/(\\w+-\\w+).*"
replace: '[$1] '
- pattern: "^\\w+\\/(\\w+-\\w+).*"
replace: '[$1] '
commitPrefix:
- pattern: "^(\\w+)-.*" # A more general match for any leading word
replace : '[$1] '
- pattern: ".*" # The final fallthrough regex that copies over the whole branch name
replace : '[$0] '
```

> Outside of `my_project`, only the `commitPrefix` entry will be attempted.
Inside of `my_project`, the repository specific pattern will be attempted.
If there is no match, the `commitPrefix` entries will then be attempted in order until a match is found

> [!IMPORTANT]
> The way golang regex works is when you use `$n` in the replacement string, where `n` is a number, it puts the nth captured subgroup at that place. If `n` is out of range because there aren't that many capture groups in the regex, it puts an empty string there.
>
Expand Down
16 changes: 16 additions & 0 deletions pkg/config/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ func loadUserConfig(configFiles []*ConfigFile, base *UserConfig) (*UserConfig, e
return base, nil
}

func (a *CommitPrefixConfigs) UnmarshalYAML(value *yaml.Node) error {
var multi []CommitPrefixConfig
err := value.Decode(&multi)
if err != nil {
var single CommitPrefixConfig
err := value.Decode(&single)
if err != nil {
return err
}
*a = []CommitPrefixConfig{single}
} else {
*a = multi
}
return nil
}
Comment on lines +215 to +229
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that go-yaml has no way to express this behavior, so I created a newtype and put the behavior on it. Taken from the comments of go-yaml/yaml#100


// Do any backward-compatibility migrations of things that have changed in the
// config over time; examples are renaming a key to a better name, moving a key
// from one container to another, or changing the type of a key (e.g. from bool
Expand Down
8 changes: 5 additions & 3 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ type GitConfig struct {
// If true, do not allow force pushes
DisableForcePushing bool `yaml:"disableForcePushing"`
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix
CommitPrefix *CommitPrefixConfig `yaml:"commitPrefix"`
CommitPrefix CommitPrefixConfigs `yaml:"commitPrefix"`
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix
CommitPrefixes map[string]CommitPrefixConfig `yaml:"commitPrefixes"`
CommitPrefixes map[string]CommitPrefixConfigs `yaml:"commitPrefixes"`
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-branch-name-prefix
BranchPrefix string `yaml:"branchPrefix"`
// If true, parse emoji strings in commit messages e.g. render :rocket: as 🚀
Expand All @@ -271,6 +271,8 @@ type GitConfig struct {
TruncateCopiedCommitHashesTo int `yaml:"truncateCopiedCommitHashesTo"`
}

type CommitPrefixConfigs []CommitPrefixConfig
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newtype just for yaml deserialization purposes to maintain backwards compatibility.


type PagerType string

func (PagerType) JSONSchemaExtend(schema *jsonschema.Schema) {
Expand Down Expand Up @@ -784,7 +786,7 @@ func GetDefaultConfig() *UserConfig {
BranchLogCmd: "git log --graph --color=always --abbrev-commit --decorate --date=relative --pretty=medium {{branchName}} --",
AllBranchesLogCmd: "git log --graph --all --color=always --abbrev-commit --decorate --date=relative --pretty=medium",
DisableForcePushing: false,
CommitPrefixes: map[string]CommitPrefixConfig(nil),
CommitPrefixes: map[string]CommitPrefixConfigs(nil),
BranchPrefix: "",
ParseEmoji: false,
TruncateCopiedCommitHashesTo: 12,
Expand Down
13 changes: 7 additions & 6 deletions pkg/gui/controllers/helpers/working_tree_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
message := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()

if message == "" {
commitPrefixConfig := self.commitPrefixConfigForRepo()
if commitPrefixConfig != nil {
commitPrefixConfigs := self.commitPrefixConfigsForRepo()
for _, commitPrefixConfig := range commitPrefixConfigs {
prefixPattern := commitPrefixConfig.Pattern
prefixReplace := commitPrefixConfig.Replace
branchName := self.refHelper.GetCheckedOutRef().Name
Expand All @@ -165,6 +165,7 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
if rgx.MatchString(branchName) {
prefix := rgx.ReplaceAllString(branchName, prefixReplace)
message = prefix
break
}
}
}
Expand Down Expand Up @@ -228,11 +229,11 @@ func (self *WorkingTreeHelper) prepareFilesForCommit() error {
return nil
}

func (self *WorkingTreeHelper) commitPrefixConfigForRepo() *config.CommitPrefixConfig {
func (self *WorkingTreeHelper) commitPrefixConfigsForRepo() config.CommitPrefixConfigs {
cfg, ok := self.c.UserConfig().Git.CommitPrefixes[self.c.Git().RepoPaths.RepoName()]
if ok {
return &cfg
return append(cfg, self.c.UserConfig().Git.CommitPrefix...)
} else {
return self.c.UserConfig().Git.CommitPrefix
}

return self.c.UserConfig().Git.CommitPrefix
}
2 changes: 1 addition & 1 deletion pkg/integration/tests/commit/commit_wip_with_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var CommitWipWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfig{"repo": {Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfigs{"repo": {{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}}
},
SetupRepo: func(shell *Shell) {
shell.NewBranch("feature/TEST-002")
Expand Down
53 changes: 53 additions & 0 deletions pkg/integration/tests/commit/commit_with_fallthrough_prefix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package commit

import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)

var CommitWithFallthroughPrefix = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Commit with defined config commitPrefix",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.CommitPrefix = config.CommitPrefixConfigs{
{Pattern: "^doesntmatch-(\\w+).*", Replace: "[BAD $1]: "},
{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[GOOD $1]: "},
}
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfigs{
"DifferentProject": {{Pattern: "^otherthatdoesn'tmatch-(\\w+).*", Replace: "[BAD $1]: "}},
}
},
SetupRepo: func(shell *Shell) {
shell.NewBranch("feature/TEST-001")
shell.CreateFile("test-commit-prefix", "This is foo bar")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
IsEmpty()

t.Views().Files().
IsFocused().
PressPrimaryAction().
Press(keys.Files.CommitChanges)

t.ExpectPopup().CommitMessagePanel().
Title(Equals("Commit summary")).
InitialText(Equals("[GOOD TEST-001]: ")).
Type("my commit message").
Cancel()

t.Views().Files().
IsFocused().
Press(keys.Files.CommitChanges)

t.ExpectPopup().CommitMessagePanel().
Title(Equals("Commit summary")).
InitialText(Equals("[GOOD TEST-001]: my commit message")).
Type(". Added something else").
Confirm()

t.Views().Commits().Focus()
t.Views().Main().Content(Contains("[GOOD TEST-001]: my commit message. Added something else"))
},
})
2 changes: 1 addition & 1 deletion pkg/integration/tests/commit/commit_with_global_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var CommitWithGlobalPrefix = NewIntegrationTest(NewIntegrationTestArgs{
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.CommitPrefix = &config.CommitPrefixConfig{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}
cfg.GetUserConfig().Git.CommitPrefix = config.CommitPrefixConfigs{{Pattern: "^\\w+\\/(\\w+-\\w+).*", Replace: "[$1]: "}}
},
SetupRepo: func(shell *Shell) {
shell.NewBranch("feature/TEST-001")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ var CommitWithNonMatchingBranchName = NewIntegrationTest(NewIntegrationTestArgs{
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.CommitPrefix = &config.CommitPrefixConfig{
cfg.GetUserConfig().Git.CommitPrefix = config.CommitPrefixConfigs{{
Pattern: "^\\w+\\/(\\w+-\\w+).*",
Replace: "[$1]: ",
}
}}
},
SetupRepo: func(shell *Shell) {
shell.NewBranch("branchnomatch")
Expand Down
6 changes: 3 additions & 3 deletions pkg/integration/tests/commit/commit_with_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ var CommitWithPrefix = NewIntegrationTest(NewIntegrationTestArgs{
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfig{
"repo": {
cfg.GetUserConfig().Git.CommitPrefixes = map[string]config.CommitPrefixConfigs{
"repo": {{
Pattern: `^\w+/(\w+-\w+).*`,
Replace: "[$1]: ",
},
}},
}
},
SetupRepo: func(shell *Shell) {
Expand Down
1 change: 1 addition & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ var tests = []*components.IntegrationTest{
commit.CommitMultiline,
commit.CommitSwitchToEditor,
commit.CommitWipWithPrefix,
commit.CommitWithFallthroughPrefix,
commit.CommitWithGlobalPrefix,
commit.CommitWithNonMatchingBranchName,
commit.CommitWithPrefix,
Expand Down
50 changes: 28 additions & 22 deletions schema/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,28 +638,7 @@
"default": false
},
"commitPrefix": {
"properties": {
"pattern": {
"type": "string",
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
"examples": [
"^\\w+\\/(\\w+-\\w+).*"
]
},
"replace": {
"type": "string",
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
"examples": [
"[$1]"
]
}
},
"additionalProperties": false,
"type": "object",
"description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix"
},
"commitPrefixes": {
"additionalProperties": {
"items": {
"properties": {
"pattern": {
"type": "string",
Expand All @@ -679,6 +658,33 @@
"additionalProperties": false,
"type": "object"
},
"type": "array",
"description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix"
},
"commitPrefixes": {
"additionalProperties": {
"items": {
"properties": {
"pattern": {
"type": "string",
"description": "pattern to match on. E.g. for 'feature/AB-123' to match on the AB-123 use \"^\\\\w+\\\\/(\\\\w+-\\\\w+).*\"",
"examples": [
"^\\w+\\/(\\w+-\\w+).*"
]
},
"replace": {
"type": "string",
"description": "Replace directive. E.g. for 'feature/AB-123' to start the commit message with 'AB-123 ' use \"[$1] \"",
"examples": [
"[$1]"
]
}
},
"additionalProperties": false,
"type": "object"
},
"type": "array"
},
"type": "object",
"description": "See https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md#predefined-commit-message-prefix"
},
Expand Down
Loading