Skip to content

Commit d2723ff

Browse files
Add option to delete local and remote tag (#4217)
- **PR Description** Option to delete both local and remote tag, closes #4203. - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [x] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [x] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc <!-- Be sure to name your PR with an imperative e.g. 'Add worktrees view' see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for examples -->
2 parents abf914c + 7db8fb8 commit d2723ff

File tree

5 files changed

+145
-0
lines changed

5 files changed

+145
-0
lines changed

pkg/gui/controllers/tags_controller.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,59 @@ func (self *TagsController) remoteDelete(tag *models.Tag) error {
177177
return nil
178178
}
179179

180+
func (self *TagsController) localAndRemoteDelete(tag *models.Tag) error {
181+
title := utils.ResolvePlaceholderString(
182+
self.c.Tr.SelectRemoteTagUpstream,
183+
map[string]string{
184+
"tagName": tag.Name,
185+
},
186+
)
187+
188+
self.c.Prompt(types.PromptOpts{
189+
Title: title,
190+
InitialContent: "origin",
191+
FindSuggestionsFunc: self.c.Helpers().Suggestions.GetRemoteSuggestionsFunc(),
192+
HandleConfirm: func(upstream string) error {
193+
confirmTitle := utils.ResolvePlaceholderString(
194+
self.c.Tr.DeleteTagTitle,
195+
map[string]string{
196+
"tagName": tag.Name,
197+
},
198+
)
199+
confirmPrompt := utils.ResolvePlaceholderString(
200+
self.c.Tr.DeleteLocalAndRemoteTagPrompt,
201+
map[string]string{
202+
"tagName": tag.Name,
203+
"upstream": upstream,
204+
},
205+
)
206+
207+
self.c.Confirm(types.ConfirmOpts{
208+
Title: confirmTitle,
209+
Prompt: confirmPrompt,
210+
HandleConfirm: func() error {
211+
return self.c.WithInlineStatus(tag, types.ItemOperationDeleting, context.TAGS_CONTEXT_KEY, func(task gocui.Task) error {
212+
self.c.LogAction(self.c.Tr.Actions.DeleteRemoteTag)
213+
if err := self.c.Git().Remote.DeleteRemoteTag(task, upstream, tag.Name); err != nil {
214+
return err
215+
}
216+
217+
self.c.LogAction(self.c.Tr.Actions.DeleteLocalTag)
218+
if err := self.c.Git().Tag.LocalDelete(tag.Name); err != nil {
219+
return err
220+
}
221+
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.COMMITS, types.TAGS}})
222+
})
223+
},
224+
})
225+
226+
return nil
227+
},
228+
})
229+
230+
return nil
231+
}
232+
180233
func (self *TagsController) delete(tag *models.Tag) error {
181234
menuTitle := utils.ResolvePlaceholderString(
182235
self.c.Tr.DeleteTagTitle,
@@ -201,6 +254,14 @@ func (self *TagsController) delete(tag *models.Tag) error {
201254
return self.remoteDelete(tag)
202255
},
203256
},
257+
{
258+
Label: self.c.Tr.DeleteLocalAndRemoteTag,
259+
Key: 'b',
260+
OpensMenu: true,
261+
OnPress: func() error {
262+
return self.localAndRemoteDelete(tag)
263+
},
264+
},
204265
}
205266

206267
return self.c.Menu(types.CreateMenuOptions{

pkg/i18n/english.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,10 @@ type TranslationSet struct {
518518
DeleteTagTitle string
519519
DeleteLocalTag string
520520
DeleteRemoteTag string
521+
DeleteLocalAndRemoteTag string
521522
SelectRemoteTagUpstream string
522523
DeleteRemoteTagPrompt string
524+
DeleteLocalAndRemoteTagPrompt string
523525
RemoteTagDeletedMessage string
524526
PushTagTitle string
525527
PushTag string
@@ -1539,9 +1541,11 @@ func EnglishTranslationSet() *TranslationSet {
15391541
DeleteTagTitle: "Delete tag '{{.tagName}}'?",
15401542
DeleteLocalTag: "Delete local tag",
15411543
DeleteRemoteTag: "Delete remote tag",
1544+
DeleteLocalAndRemoteTag: "Delete local and remote tag",
15421545
RemoteTagDeletedMessage: "Remote tag deleted",
15431546
SelectRemoteTagUpstream: "Remote from which to remove tag '{{.tagName}}':",
15441547
DeleteRemoteTagPrompt: "Are you sure you want to delete the remote tag '{{.tagName}}' from '{{.upstream}}'?",
1548+
DeleteLocalAndRemoteTagPrompt: "Are you sure you want to delete '{{.tagName}}' from both your machine and from '{{.upstream}}'?",
15451549
PushTagTitle: "Remote to push tag '{{.tagName}}' to:",
15461550
// Using 'push tag' rather than just 'push' to disambiguate from a global push
15471551
PushTag: "Push tag",

pkg/integration/components/shell.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ func (self *Shell) Revert(ref string) *Shell {
190190
return self.RunCommand([]string{"git", "revert", ref})
191191
}
192192

193+
func (self *Shell) AssertRemoteTagNotFound(upstream, name string) *Shell {
194+
return self.RunCommandExpectError([]string{"git", "ls-remote", "--exit-code", upstream, fmt.Sprintf("refs/tags/%s", name)})
195+
}
196+
193197
func (self *Shell) CreateLightweightTag(name string, ref string) *Shell {
194198
return self.RunCommand([]string{"git", "tag", name, ref})
195199
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package tag
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var DeleteLocalAndRemote = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Create and delete both local and remote annotated tag",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {},
13+
SetupRepo: func(shell *Shell) {
14+
shell.EmptyCommit("initial commit")
15+
shell.CloneIntoRemote("origin")
16+
},
17+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
18+
t.Views().Tags().
19+
Focus().
20+
IsEmpty().
21+
Press(keys.Universal.New).
22+
Tap(func() {
23+
t.ExpectPopup().CommitMessagePanel().
24+
Title(Equals("Tag name")).
25+
Type("new-tag").
26+
SwitchToDescription().
27+
Title(Equals("Tag description")).
28+
Type("message").
29+
SwitchToSummary().
30+
Confirm()
31+
}).
32+
Lines(
33+
MatchesRegexp(`new-tag.*message`).IsSelected(),
34+
).
35+
Press(keys.Universal.Push).
36+
Tap(func() {
37+
t.ExpectPopup().Prompt().
38+
Title(Equals("Remote to push tag 'new-tag' to:")).
39+
InitialText(Equals("origin")).
40+
SuggestionLines(
41+
Contains("origin"),
42+
).
43+
Confirm()
44+
}).
45+
Press(keys.Universal.Remove).
46+
Tap(func() {
47+
t.ExpectPopup().
48+
Menu().
49+
Title(Equals("Delete tag 'new-tag'?")).
50+
Select(Contains("Delete local and remote tag")).
51+
Confirm()
52+
}).
53+
Tap(func() {
54+
t.ExpectPopup().Prompt().
55+
Title(Equals("Remote from which to remove tag 'new-tag':")).
56+
InitialText(Equals("origin")).
57+
SuggestionLines(
58+
Contains("origin"),
59+
).
60+
Confirm()
61+
}).
62+
Tap(func() {
63+
t.ExpectPopup().
64+
Confirmation().
65+
Title(Equals("Delete tag 'new-tag'?")).
66+
Content(Equals("Are you sure you want to delete 'new-tag' from both your machine and from 'origin'?")).
67+
Confirm()
68+
}).
69+
IsEmpty().
70+
Press(keys.Universal.New).
71+
Tap(func() {
72+
t.Shell().AssertRemoteTagNotFound("origin", "new-tag")
73+
})
74+
},
75+
})

pkg/integration/tests/test_list.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ var tests = []*components.IntegrationTest{
356356
tag.CreateWhileCommitting,
357357
tag.CrudAnnotated,
358358
tag.CrudLightweight,
359+
tag.DeleteLocalAndRemote,
359360
tag.ForceTagAnnotated,
360361
tag.ForceTagLightweight,
361362
tag.Reset,

0 commit comments

Comments
 (0)