mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-11-28 09:08:41 +02:00
add tags panel
This commit is contained in:
parent
cea24c2cf9
commit
3c13229145
@ -1,6 +1,8 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
@ -14,6 +16,7 @@ type Commit struct {
|
||||
DisplayString string
|
||||
Action string // one of "", "pick", "edit", "squash", "reword", "drop", "fixup"
|
||||
Copied bool // to know if this commit is ready to be cherry-picked somewhere
|
||||
Tags []string
|
||||
}
|
||||
|
||||
// GetDisplayStrings is a function.
|
||||
@ -52,9 +55,12 @@ func (c *Commit) GetDisplayStrings(isFocused bool) []string {
|
||||
}
|
||||
|
||||
actionString := ""
|
||||
tagString := ""
|
||||
if c.Action != "" {
|
||||
actionString = cyan.Sprint(utils.WithPadding(c.Action, 7)) + " "
|
||||
} else if len(c.Tags) > 0 {
|
||||
tagString = utils.ColoredString(strings.Join(c.Tags, " "), color.FgMagenta) + " "
|
||||
}
|
||||
|
||||
return []string{shaColor.Sprint(c.Sha), actionString + defaultColor.Sprint(c.Name)}
|
||||
return []string{shaColor.Sprint(c.Sha), actionString + tagString + defaultColor.Sprint(c.Name)}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ func (c *CommitListBuilder) GetCommits() ([]*Commit, error) {
|
||||
Name: strings.Join(splitLine[1:], " "),
|
||||
Status: status,
|
||||
DisplayString: strings.Join(splitLine, " "),
|
||||
// TODO: add tags here
|
||||
})
|
||||
}
|
||||
if rebaseMode != "" {
|
||||
|
@ -419,7 +419,7 @@ func (c *GitCommand) Push(branchName string, force bool, upstream string, ask fu
|
||||
setUpstreamArg = "--set-upstream " + upstream
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf("git push %s %s", forceFlag, setUpstreamArg)
|
||||
cmd := fmt.Sprintf("git push --follow-tags %s %s", forceFlag, setUpstreamArg)
|
||||
return c.OSCommand.DetectUnamePass(cmd, ask)
|
||||
}
|
||||
|
||||
@ -1099,3 +1099,19 @@ func (c *GitCommand) RenameRemote(oldRemoteName string, newRemoteName string) er
|
||||
func (c *GitCommand) UpdateRemoteUrl(remoteName string, updatedUrl string) error {
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git remote set-url %s %s", remoteName, updatedUrl))
|
||||
}
|
||||
|
||||
func (c *GitCommand) CreateLightweightTag(tagName string, commitSha string) error {
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git tag %s %s", tagName, commitSha))
|
||||
}
|
||||
|
||||
func (c *GitCommand) ShowTag(tagName string) (string, error) {
|
||||
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git tag -n99 %s", tagName))
|
||||
}
|
||||
|
||||
func (c *GitCommand) DeleteTag(tagName string) error {
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git tag -d %s", tagName))
|
||||
}
|
||||
|
||||
func (c *GitCommand) PushTag(remoteName string, tagName string) error {
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git push %s %s", remoteName, tagName))
|
||||
}
|
||||
|
78
pkg/commands/loading_tags.go
Normal file
78
pkg/commands/loading_tags.go
Normal file
@ -0,0 +1,78 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
const semverRegex = `v?((\d+\.?)+)([^\d]?.*)`
|
||||
|
||||
func (c *GitCommand) GetTags() ([]*Tag, error) {
|
||||
// get remote branches
|
||||
remoteBranchesStr, err := c.OSCommand.RunCommandWithOutput("git tag --list")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content := utils.TrimTrailingNewline(remoteBranchesStr)
|
||||
if content == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
split := strings.Split(content, "\n")
|
||||
|
||||
// first step is to get our remotes from go-git
|
||||
tags := make([]*Tag, len(split))
|
||||
for i, tagName := range split {
|
||||
|
||||
tags[i] = &Tag{
|
||||
Name: tagName,
|
||||
}
|
||||
}
|
||||
|
||||
// now lets sort our tags by name numerically
|
||||
re := regexp.MustCompile(semverRegex)
|
||||
|
||||
// the reason this is complicated is because we're both sorting alphabetically
|
||||
// and when we're dealing with semver strings
|
||||
sort.Slice(tags, func(i, j int) bool {
|
||||
a := tags[i].Name
|
||||
b := tags[j].Name
|
||||
|
||||
matchA := re.FindStringSubmatch(a)
|
||||
matchB := re.FindStringSubmatch(b)
|
||||
|
||||
if len(matchA) > 0 && len(matchB) > 0 {
|
||||
numbersA := strings.Split(matchA[1], ".")
|
||||
numbersB := strings.Split(matchB[1], ".")
|
||||
k := 0
|
||||
for {
|
||||
if len(numbersA) == k && len(numbersB) == k {
|
||||
break
|
||||
}
|
||||
if len(numbersA) == k {
|
||||
return true
|
||||
}
|
||||
if len(numbersB) == k {
|
||||
return false
|
||||
}
|
||||
if mustConvertToInt(numbersA[k]) < mustConvertToInt(numbersB[k]) {
|
||||
return true
|
||||
}
|
||||
if mustConvertToInt(numbersA[k]) > mustConvertToInt(numbersB[k]) {
|
||||
return false
|
||||
}
|
||||
k++
|
||||
}
|
||||
|
||||
return strings.ToLower(matchA[3]) < strings.ToLower(matchB[3])
|
||||
}
|
||||
|
||||
return strings.ToLower(a) < strings.ToLower(b)
|
||||
})
|
||||
|
||||
return tags, nil
|
||||
}
|
11
pkg/commands/tag.go
Normal file
11
pkg/commands/tag.go
Normal file
@ -0,0 +1,11 @@
|
||||
package commands
|
||||
|
||||
// Tag : A git tag
|
||||
type Tag struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// GetDisplayStrings returns the display string of a remote
|
||||
func (r *Tag) GetDisplayStrings(isFocused bool) []string {
|
||||
return []string{r.Name}
|
||||
}
|
@ -80,6 +80,10 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gui.refreshTags(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.Update(func(g *gocui.Gui) error {
|
||||
builder, err := commands.NewBranchListBuilder(gui.Log, gui.GitCommand)
|
||||
if err != nil {
|
||||
@ -373,7 +377,7 @@ func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
|
||||
}
|
||||
|
||||
func (gui *Gui) onBranchesTabClick(tabIndex int) error {
|
||||
contexts := []string{"local-branches", "remotes", "tabs"}
|
||||
contexts := []string{"local-branches", "remotes", "tags"}
|
||||
branchesView := gui.getBranchesView()
|
||||
branchesView.TabIndex = tabIndex
|
||||
|
||||
@ -388,6 +392,7 @@ func (gui *Gui) switchBranchesPanelContext(context string) error {
|
||||
"local-branches": 0,
|
||||
"remotes": 1,
|
||||
"remote-branches": 1,
|
||||
"tags": 2,
|
||||
}
|
||||
|
||||
branchesView.TabIndex = contextTabIndexMap[context]
|
||||
@ -399,6 +404,8 @@ func (gui *Gui) switchBranchesPanelContext(context string) error {
|
||||
return gui.renderRemotesWithSelection()
|
||||
case "remote-branches":
|
||||
return gui.renderRemoteBranchesWithSelection()
|
||||
case "tags":
|
||||
return gui.renderTagsWithSelection()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -584,3 +584,30 @@ func (gui *Gui) handleCreateCommitResetMenu(g *gocui.Gui, v *gocui.View) error {
|
||||
|
||||
return gui.createMenu(fmt.Sprintf("%s %s", gui.Tr.SLocalize("resetTo"), commit.Sha), options, len(options), handleMenuPress)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleTagCommit(g *gocui.Gui, v *gocui.View) error {
|
||||
// TODO: bring up menu asking if you want to make a lightweight or annotated tag
|
||||
// if annotated, switch to a subprocess to create the message
|
||||
|
||||
commit := gui.getSelectedCommit(g)
|
||||
if commit == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return gui.handleCreateLightweightTag(commit.Sha)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCreateLightweightTag(commitSha string) error {
|
||||
return gui.createPromptPanel(gui.g, gui.getCommitsView(), gui.Tr.SLocalize("TagNameTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := gui.GitCommand.CreateLightweightTag(v.Buffer(), commitSha); err != nil {
|
||||
return gui.createErrorPanel(g, err.Error())
|
||||
}
|
||||
if err := gui.refreshCommits(g); err != nil {
|
||||
return gui.createErrorPanel(g, err.Error())
|
||||
}
|
||||
if err := gui.refreshTags(); err != nil {
|
||||
return gui.createErrorPanel(g, err.Error())
|
||||
}
|
||||
return gui.handleCommitSelect(g, v)
|
||||
})
|
||||
}
|
||||
|
@ -120,6 +120,10 @@ type remoteBranchesState struct {
|
||||
SelectedLine int
|
||||
}
|
||||
|
||||
type tagsPanelState struct {
|
||||
SelectedLine int
|
||||
}
|
||||
|
||||
type commitPanelState struct {
|
||||
SelectedLine int
|
||||
SpecificDiffMode bool
|
||||
@ -148,6 +152,7 @@ type panelStates struct {
|
||||
Branches *branchPanelState
|
||||
Remotes *remotePanelState
|
||||
RemoteBranches *remoteBranchesState
|
||||
Tags *tagsPanelState
|
||||
Commits *commitPanelState
|
||||
Stash *stashPanelState
|
||||
Menu *menuPanelState
|
||||
@ -166,6 +171,7 @@ type guiState struct {
|
||||
DiffEntries []*commands.Commit
|
||||
Remotes []*commands.Remote
|
||||
RemoteBranches []*commands.RemoteBranch
|
||||
Tags []*commands.Tag
|
||||
MenuItemCount int // can't store the actual list because it's of interface{} type
|
||||
PreviousView string
|
||||
Platform commands.Platform
|
||||
@ -198,6 +204,7 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma
|
||||
Branches: &branchPanelState{SelectedLine: 0},
|
||||
Remotes: &remotePanelState{SelectedLine: 0},
|
||||
RemoteBranches: &remoteBranchesState{SelectedLine: -1},
|
||||
Tags: &tagsPanelState{SelectedLine: -1},
|
||||
Commits: &commitPanelState{SelectedLine: -1},
|
||||
CommitFiles: &commitFilesPanelState{SelectedLine: -1},
|
||||
Stash: &stashPanelState{SelectedLine: -1},
|
||||
@ -497,7 +504,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
||||
return err
|
||||
}
|
||||
branchesView.Title = gui.Tr.SLocalize("BranchesTitle")
|
||||
branchesView.Tabs = []string{"Local Branches", "Remotes"}
|
||||
branchesView.Tabs = []string{"Local Branches", "Remotes", "Tags"}
|
||||
branchesView.FgColor = textColor
|
||||
}
|
||||
|
||||
|
@ -402,6 +402,38 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||
Handler: gui.handleFastForward,
|
||||
Description: gui.Tr.SLocalize("FastForward"),
|
||||
},
|
||||
{
|
||||
ViewName: "branches",
|
||||
Contexts: []string{"tags"},
|
||||
Key: gocui.KeySpace,
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleCheckoutTag,
|
||||
Description: gui.Tr.SLocalize("checkout"),
|
||||
},
|
||||
{
|
||||
ViewName: "branches",
|
||||
Contexts: []string{"tags"},
|
||||
Key: 'd',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleDeleteTag,
|
||||
Description: gui.Tr.SLocalize("deleteTag"),
|
||||
},
|
||||
{
|
||||
ViewName: "branches",
|
||||
Contexts: []string{"tags"},
|
||||
Key: 'P',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handlePushTag,
|
||||
Description: gui.Tr.SLocalize("pushTags"),
|
||||
},
|
||||
{
|
||||
ViewName: "branches",
|
||||
Contexts: []string{"tags"},
|
||||
Key: 'n',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleCreateTag,
|
||||
Description: gui.Tr.SLocalize("createTag"),
|
||||
},
|
||||
{
|
||||
ViewName: "branches",
|
||||
Key: ']',
|
||||
@ -555,6 +587,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
||||
Handler: gui.handleToggleDiffCommit,
|
||||
Description: gui.Tr.SLocalize("CommitsDiff"),
|
||||
},
|
||||
{
|
||||
ViewName: "commits",
|
||||
Key: 'T',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleTagCommit,
|
||||
Description: gui.Tr.SLocalize("tagCommit"),
|
||||
},
|
||||
{
|
||||
ViewName: "stash",
|
||||
Key: gocui.KeySpace,
|
||||
|
@ -116,6 +116,16 @@ func (gui *Gui) getListViews() []*listView {
|
||||
gui: gui,
|
||||
rendersToMainView: true,
|
||||
},
|
||||
{
|
||||
viewName: "branches",
|
||||
context: "tags",
|
||||
getItemsLength: func() int { return len(gui.State.Tags) },
|
||||
getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Tags.SelectedLine },
|
||||
handleFocus: gui.handleTagSelect,
|
||||
handleItemSelect: gui.handleTagSelect,
|
||||
gui: gui,
|
||||
rendersToMainView: true,
|
||||
},
|
||||
{
|
||||
viewName: "commits",
|
||||
getItemsLength: func() int { return len(gui.State.Commits) },
|
||||
|
@ -35,6 +35,9 @@ func (gui *Gui) handleRemoteSelect(g *gocui.Gui, v *gocui.View) error {
|
||||
gui.getMainView().Title = "Remote"
|
||||
|
||||
remote := gui.getSelectedRemote()
|
||||
if remote == nil {
|
||||
return gui.renderString(g, "main", "No remotes")
|
||||
}
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Remotes.SelectedLine, len(gui.State.Remotes), v); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -42,8 +45,6 @@ func (gui *Gui) handleRemoteSelect(g *gocui.Gui, v *gocui.View) error {
|
||||
return gui.renderString(g, "main", fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n")))
|
||||
}
|
||||
|
||||
// gui.refreshStatus is called at the end of this because that's when we can
|
||||
// be sure there is a state.Remotes array to pick the current remote from
|
||||
func (gui *Gui) refreshRemotes() error {
|
||||
prevSelectedRemote := gui.getSelectedRemote()
|
||||
|
||||
@ -92,6 +93,9 @@ func (gui *Gui) renderRemotesWithSelection() error {
|
||||
func (gui *Gui) handleRemoteEnter(g *gocui.Gui, v *gocui.View) error {
|
||||
// naive implementation: get the branches and render them to the list, change the context
|
||||
remote := gui.getSelectedRemote()
|
||||
if remote == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
gui.State.RemoteBranches = remote.Branches
|
||||
|
||||
|
149
pkg/gui/tags_panel.go
Normal file
149
pkg/gui/tags_panel.go
Normal file
@ -0,0 +1,149 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||
)
|
||||
|
||||
// list panel functions
|
||||
|
||||
func (gui *Gui) getSelectedTag() *commands.Tag {
|
||||
selectedLine := gui.State.Panels.Tags.SelectedLine
|
||||
if selectedLine == -1 || len(gui.State.Tags) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return gui.State.Tags[selectedLine]
|
||||
}
|
||||
|
||||
func (gui *Gui) handleTagSelect(g *gocui.Gui, v *gocui.View) error {
|
||||
if gui.popupPanelFocused() {
|
||||
return nil
|
||||
}
|
||||
|
||||
gui.State.SplitMainPanel = false
|
||||
|
||||
if _, err := gui.g.SetCurrentView(v.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gui.getMainView().Title = "Tag"
|
||||
|
||||
tag := gui.getSelectedTag()
|
||||
if tag == nil {
|
||||
return gui.renderString(g, "main", "No tags")
|
||||
}
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Tags.SelectedLine, len(gui.State.Tags), v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
show, err := gui.GitCommand.ShowTag(tag.Name)
|
||||
if err != nil {
|
||||
show = ""
|
||||
}
|
||||
|
||||
graph, err := gui.GitCommand.GetBranchGraph(tag.Name)
|
||||
if err != nil {
|
||||
graph = "No graph for tag " + tag.Name
|
||||
}
|
||||
|
||||
_ = gui.renderString(g, "main", fmt.Sprintf("%s\n%s", show, graph))
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) refreshTags() error {
|
||||
tags, err := gui.GitCommand.GetTags()
|
||||
if err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
|
||||
gui.State.Tags = tags
|
||||
|
||||
if gui.getBranchesView().Context == "tags" {
|
||||
gui.renderTagsWithSelection()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) renderTagsWithSelection() error {
|
||||
branchesView := gui.getBranchesView()
|
||||
|
||||
gui.refreshSelectedLine(&gui.State.Panels.Tags.SelectedLine, len(gui.State.Tags))
|
||||
if err := gui.renderListPanel(branchesView, gui.State.Tags); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gui.handleTagSelect(gui.g, branchesView); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCheckoutTag(g *gocui.Gui, v *gocui.View) error {
|
||||
tag := gui.getSelectedTag()
|
||||
if tag == nil {
|
||||
return nil
|
||||
}
|
||||
if err := gui.handleCheckoutBranch(tag.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
return gui.switchBranchesPanelContext("local-branches")
|
||||
}
|
||||
|
||||
func (gui *Gui) handleDeleteTag(g *gocui.Gui, v *gocui.View) error {
|
||||
tag := gui.getSelectedTag()
|
||||
if tag == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
prompt := gui.Tr.TemplateLocalize(
|
||||
"DeleteTagPrompt",
|
||||
Teml{
|
||||
"tagName": tag.Name,
|
||||
},
|
||||
)
|
||||
|
||||
return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("DeleteTagTitle"), prompt, func(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := gui.GitCommand.DeleteTag(tag.Name); err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
return gui.refreshTags()
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func (gui *Gui) handlePushTag(g *gocui.Gui, v *gocui.View) error {
|
||||
tag := gui.getSelectedTag()
|
||||
if tag == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
title := gui.Tr.TemplateLocalize(
|
||||
"PushTagTitle",
|
||||
Teml{
|
||||
"tagName": tag.Name,
|
||||
},
|
||||
)
|
||||
|
||||
return gui.createPromptPanel(gui.g, v, title, "origin", func(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := gui.GitCommand.PushTag(v.Buffer(), tag.Name); err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
return gui.refreshTags()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCreateTag(g *gocui.Gui, v *gocui.View) error {
|
||||
return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("CreateTagTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
|
||||
// leaving commit SHA blank so that we're just creating the tag for the current commit
|
||||
if err := gui.GitCommand.CreateLightweightTag(v.Buffer(), ""); err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
return gui.refreshTags()
|
||||
})
|
||||
}
|
@ -112,6 +112,8 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
|
||||
return gui.handleRemoteSelect(g, v)
|
||||
case "remote-branches":
|
||||
return gui.handleRemoteBranchSelect(g, v)
|
||||
case "tags":
|
||||
return gui.handleTagSelect(g, v)
|
||||
default:
|
||||
return errors.New("unknown branches panel context: " + branchesView.Context)
|
||||
}
|
||||
|
@ -885,6 +885,33 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
||||
}, &i18n.Message{
|
||||
ID: "editRemote",
|
||||
Other: "edit remote",
|
||||
}, &i18n.Message{
|
||||
ID: "tagCommit",
|
||||
Other: "tag commit",
|
||||
}, &i18n.Message{
|
||||
ID: "TagNameTitle",
|
||||
Other: "Tag name:",
|
||||
}, &i18n.Message{
|
||||
ID: "deleteTag",
|
||||
Other: "delete tag",
|
||||
}, &i18n.Message{
|
||||
ID: "DeleteTagTitle",
|
||||
Other: "Delete tag",
|
||||
}, &i18n.Message{
|
||||
ID: "DeleteTagPrompt",
|
||||
Other: "Are you sure you want to delete tag '{{.tagName}}'?",
|
||||
}, &i18n.Message{
|
||||
ID: "PushTagTitle",
|
||||
Other: "remote to push tag '{{.tagName}}' to:",
|
||||
}, &i18n.Message{
|
||||
ID: "pushTags",
|
||||
Other: "push tags",
|
||||
}, &i18n.Message{
|
||||
ID: "createTag",
|
||||
Other: "create tag",
|
||||
}, &i18n.Message{
|
||||
ID: "CreateTagTitle",
|
||||
Other: "Tag name:",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user