diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2023-07-31 11:40:40 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-31 11:40:40 +0200 |
commit | 045bce5dfc5c59215f591a0dca2b95ef036a1e68 (patch) | |
tree | 8cbf03e0daac97378faa2f4fe15dc249772795c4 | |
parent | 71d2fd37e2ff8214d5af3135ab3a355971789dc2 (diff) | |
parent | 38274796432eabd3727580ba7d1bcfba6bcbe99f (diff) |
Allow force-tagging if tag exists (#2827)
-rw-r--r-- | pkg/commands/git_commands/tag.go | 18 | ||||
-rw-r--r-- | pkg/gui/controllers/helpers/tags_helper.go | 29 | ||||
-rw-r--r-- | pkg/gui/controllers/sync_controller.go | 15 | ||||
-rw-r--r-- | pkg/i18n/english.go | 6 | ||||
-rw-r--r-- | pkg/integration/tests/sync/force_push.go | 2 | ||||
-rw-r--r-- | pkg/integration/tests/sync/force_push_multiple_matching.go | 2 | ||||
-rw-r--r-- | pkg/integration/tests/sync/force_push_multiple_upstream.go | 2 | ||||
-rw-r--r-- | pkg/integration/tests/tag/force_tag_annotated.go | 47 | ||||
-rw-r--r-- | pkg/integration/tests/tag/force_tag_lightweight.go | 43 | ||||
-rw-r--r-- | pkg/integration/tests/test_list.go | 2 |
10 files changed, 154 insertions, 12 deletions
diff --git a/pkg/commands/git_commands/tag.go b/pkg/commands/git_commands/tag.go index fb87db3b9..2517ce380 100644 --- a/pkg/commands/git_commands/tag.go +++ b/pkg/commands/git_commands/tag.go @@ -12,16 +12,19 @@ func NewTagCommands(gitCommon *GitCommon) *TagCommands { } } -func (self *TagCommands) CreateLightweight(tagName string, ref string) error { - cmdArgs := NewGitCmd("tag").Arg("--", tagName). +func (self *TagCommands) CreateLightweight(tagName string, ref string, force bool) error { + cmdArgs := NewGitCmd("tag"). + ArgIf(force, "--force"). + Arg("--", tagName). ArgIf(len(ref) > 0, ref). ToArgv() return self.cmd.New(cmdArgs).Run() } -func (self *TagCommands) CreateAnnotated(tagName, ref, msg string) error { +func (self *TagCommands) CreateAnnotated(tagName, ref, msg string, force bool) error { cmdArgs := NewGitCmd("tag").Arg(tagName). + ArgIf(force, "--force"). ArgIf(len(ref) > 0, ref). Arg("-m", msg). ToArgv() @@ -29,6 +32,15 @@ func (self *TagCommands) CreateAnnotated(tagName, ref, msg string) error { return self.cmd.New(cmdArgs).Run() } +func (self *TagCommands) HasTag(tagName string) bool { + cmdArgs := NewGitCmd("show-ref"). + Arg("--tags", "--quiet", "--verify", "--"). + Arg("refs/tags/" + tagName). + ToArgv() + + return self.cmd.New(cmdArgs).Run() == nil +} + func (self *TagCommands) Delete(tagName string) error { cmdArgs := NewGitCmd("tag").Arg("-d", tagName). ToArgv() diff --git a/pkg/gui/controllers/helpers/tags_helper.go b/pkg/gui/controllers/helpers/tags_helper.go index 47f2115ce..51957355a 100644 --- a/pkg/gui/controllers/helpers/tags_helper.go +++ b/pkg/gui/controllers/helpers/tags_helper.go @@ -4,6 +4,7 @@ import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/utils" ) type TagsHelper struct { @@ -19,16 +20,16 @@ func NewTagsHelper(c *HelperCommon, commitsHelper *CommitsHelper) *TagsHelper { } func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error { - onConfirm := func(tagName string, description string) error { + doCreateTag := func(tagName string, description string, force bool) error { return self.c.WithWaitingStatus(self.c.Tr.CreatingTag, func(gocui.Task) error { if description != "" { self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag) - if err := self.c.Git().Tag.CreateAnnotated(tagName, ref, description); err != nil { + if err := self.c.Git().Tag.CreateAnnotated(tagName, ref, description, force); err != nil { return self.c.Error(err) } } else { self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag) - if err := self.c.Git().Tag.CreateLightweight(tagName, ref); err != nil { + if err := self.c.Git().Tag.CreateLightweight(tagName, ref, force); err != nil { return self.c.Error(err) } } @@ -41,6 +42,28 @@ func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error { }) } + onConfirm := func(tagName string, description string) error { + if self.c.Git().Tag.HasTag(tagName) { + prompt := utils.ResolvePlaceholderString( + self.c.Tr.ForceTagPrompt, + map[string]string{ + "tagName": tagName, + "cancelKey": self.c.UserConfig.Keybinding.Universal.Return, + "confirmKey": self.c.UserConfig.Keybinding.Universal.Confirm, + }, + ) + return self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.ForceTag, + Prompt: prompt, + HandleConfirm: func() error { + return doCreateTag(tagName, description, true) + }, + }) + } else { + return doCreateTag(tagName, description, false) + } + } + return self.commitsHelper.OpenCommitMessagePanel( &OpenCommitMessagePanelOpts{ CommitIndex: context.NoCommitIndex, diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index 9fa2da09c..2ec22b2a4 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -8,6 +8,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/utils" ) type SyncController struct { @@ -186,7 +187,7 @@ func (self *SyncController) pushAux(opts pushOpts) error { } _ = self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.ForcePush, - Prompt: self.c.Tr.ForcePushPrompt, + Prompt: self.forcePushPrompt(), HandleConfirm: func() error { newOpts := opts newOpts.force = true @@ -210,10 +211,20 @@ func (self *SyncController) requestToForcePush(opts pushOpts) error { return self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.ForcePush, - Prompt: self.c.Tr.ForcePushPrompt, + Prompt: self.forcePushPrompt(), HandleConfirm: func() error { opts.force = true return self.pushAux(opts) }, }) } + +func (self *SyncController) forcePushPrompt() string { + return utils.ResolvePlaceholderString( + self.c.Tr.ForcePushPrompt, + map[string]string{ + "cancelKey": self.c.UserConfig.Keybinding.Universal.Return, + "confirmKey": self.c.UserConfig.Keybinding.Universal.Confirm, + }, + ) +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 5aa6bd3c9..84f881c5d 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -359,6 +359,8 @@ type TranslationSet struct { PushTag string CreateTag string CreatingTag string + ForceTag string + ForceTagPrompt string FetchRemote string FetchingRemoteStatus string CheckoutCommit string @@ -874,7 +876,7 @@ func EnglishTranslationSet() TranslationSet { OpenConfig: "Open config file", EditConfig: "Edit config file", ForcePush: "Force push", - ForcePushPrompt: "Your branch has diverged from the remote branch. Press 'esc' to cancel, or 'enter' to force push.", + ForcePushPrompt: "Your branch has diverged from the remote branch. Press {{.cancelKey}} to cancel, or {{.confirmKey}} to force push.", ForcePushDisabled: "Your branch has diverged from the remote branch and you've disabled force pushing", UpdatesRejectedAndForcePushDisabled: "Updates were rejected and you have disabled force pushing", CheckForUpdate: "Check for update", @@ -1102,6 +1104,8 @@ func EnglishTranslationSet() TranslationSet { PushTag: "Push tag", CreateTag: "Create tag", CreatingTag: "Creating tag", + ForceTag: "Force Tag", + ForceTagPrompt: "The tag '{{.tagName}}' exists already. Press {{.cancelKey}} to cancel, or {{.confirmKey}} to overwrite.", FetchRemote: "Fetch remote", FetchingRemoteStatus: "Fetching remote", CheckoutCommit: "Checkout commit", diff --git a/pkg/integration/tests/sync/force_push.go b/pkg/integration/tests/sync/force_push.go index cf8ec60f1..89d8a8371 100644 --- a/pkg/integration/tests/sync/force_push.go +++ b/pkg/integration/tests/sync/force_push.go @@ -32,7 +32,7 @@ var ForcePush = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Confirmation(). Title(Equals("Force push")). - Content(Equals("Your branch has diverged from the remote branch. Press 'esc' to cancel, or 'enter' to force push.")). + Content(Equals("Your branch has diverged from the remote branch. Press <esc> to cancel, or <enter> to force push.")). Confirm() t.Views().Commits(). diff --git a/pkg/integration/tests/sync/force_push_multiple_matching.go b/pkg/integration/tests/sync/force_push_multiple_matching.go index 4f9998bb1..37c43f264 100644 --- a/pkg/integration/tests/sync/force_push_multiple_matching.go +++ b/pkg/integration/tests/sync/force_push_multiple_matching.go @@ -34,7 +34,7 @@ var ForcePushMultipleMatching = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Confirmation(). Title(Equals("Force push")). - Content(Equals("Your branch has diverged from the remote branch. Press 'esc' to cancel, or 'enter' to force push.")). + Content(Equals("Your branch has diverged from the remote branch. Press <esc> to cancel, or <enter> to force push.")). Confirm() t.Views().Commits(). diff --git a/pkg/integration/tests/sync/force_push_multiple_upstream.go b/pkg/integration/tests/sync/force_push_multiple_upstream.go index f94e33e22..1ea512720 100644 --- a/pkg/integration/tests/sync/force_push_multiple_upstream.go +++ b/pkg/integration/tests/sync/force_push_multiple_upstream.go @@ -33,7 +33,7 @@ var ForcePushMultipleUpstream = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Confirmation(). Title(Equals("Force push")). - Content(Equals("Your branch has diverged from the remote branch. Press 'esc' to cancel, or 'enter' to force push.")). + Content(Equals("Your branch has diverged from the remote branch. Press <esc> to cancel, or <enter> to force push.")). Confirm() t.Views().Commits(). diff --git a/pkg/integration/tests/tag/force_tag_annotated.go b/pkg/integration/tests/tag/force_tag_annotated.go new file mode 100644 index 000000000..1f9e2f09b --- /dev/null +++ b/pkg/integration/tests/tag/force_tag_annotated.go @@ -0,0 +1,47 @@ +package tag + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var ForceTagAnnotated = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Overwrite an annotated tag that already exists", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("first commit") + shell.CreateAnnotatedTag("new-tag", "message", "HEAD") + shell.EmptyCommit("second commit") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("second commit").IsSelected(), + Contains("new-tag").Contains("first commit"), + ). + Press(keys.Commits.CreateTag). + Tap(func() { + t.ExpectPopup().CommitMessagePanel(). + Title(Equals("Tag name")). + Type("new-tag"). + SwitchToDescription(). + Title(Equals("Tag description")). + Type("message"). + SwitchToSummary(). + Confirm() + }). + Tap(func() { + t.ExpectPopup().Confirmation(). + Title(Equals("Force Tag")). + Content(Contains("The tag 'new-tag' exists already. Press <esc> to cancel, or <enter> to overwrite.")). + Confirm() + }). + Lines( + Contains("new-tag").Contains("second commit"), + DoesNotContain("new-tag").Contains("first commit"), + ) + }, +}) diff --git a/pkg/integration/tests/tag/force_tag_lightweight.go b/pkg/integration/tests/tag/force_tag_lightweight.go new file mode 100644 index 000000000..1f24b624c --- /dev/null +++ b/pkg/integration/tests/tag/force_tag_lightweight.go @@ -0,0 +1,43 @@ +package tag + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var ForceTagLightweight = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Overwrite a lightweight tag that already exists", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("first commit") + shell.CreateLightweightTag("new-tag", "HEAD") + shell.EmptyCommit("second commit") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + Lines( + Contains("second commit").IsSelected(), + Contains("new-tag").Contains("first commit"), + ). + Press(keys.Commits.CreateTag). + Tap(func() { + t.ExpectPopup().CommitMessagePanel(). + Title(Equals("Tag name")). + Type("new-tag"). + Confirm() + }). + Tap(func() { + t.ExpectPopup().Confirmation(). + Title(Equals("Force Tag")). + Content(Contains("The tag 'new-tag' exists already. Press <esc> to cancel, or <enter> to overwrite.")). + Confirm() + }). + Lines( + Contains("new-tag").Contains("second commit"), + DoesNotContain("new-tag").Contains("first commit"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index dfcd6c0ea..d7870ff49 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -214,6 +214,8 @@ var tests = []*components.IntegrationTest{ tag.CreateWhileCommitting, tag.CrudAnnotated, tag.CrudLightweight, + tag.ForceTagAnnotated, + tag.ForceTagLightweight, tag.Reset, ui.Accordion, ui.DoublePopup, |