Skip to content

Commit 6bd898e

Browse files
committed
start on alias delete
1 parent 494598a commit 6bd898e

File tree

4 files changed

+110
-11
lines changed

4 files changed

+110
-11
lines changed

command/alias.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func init() {
1414
RootCmd.AddCommand(aliasCmd)
1515
aliasCmd.AddCommand(aliasSetCmd)
1616
aliasCmd.AddCommand(aliasListCmd)
17+
aliasCmd.AddCommand(aliasDeleteCmd)
1718
}
1819

1920
var aliasCmd = &cobra.Command{
@@ -23,10 +24,8 @@ var aliasCmd = &cobra.Command{
2324

2425
var aliasSetCmd = &cobra.Command{
2526
Use: "set <alias> <expansion>",
26-
// NB: Even when inside of a single-quoted string, cobra was noticing and parsing any flags
27-
// used in an alias expansion string argument. Since this command needs no flags, I disabled their
28-
// parsing. If we ever want to add flags to alias set we'll have to figure this out. I tested on
29-
// linux in various shells against cobra 1.0; others on macos did /not/ see the same behavior.
27+
// NB: this allows a user to eschew quotes when specifiying an alias expansion. We'll have to
28+
// revisit it if we ever want to add flags to alias set but we have no current plans for that.
3029
DisableFlagParsing: true,
3130
Short: "Create a shortcut for a gh command",
3231
Long: `This command lets you write your own shortcuts for running gh. They can be simple strings or accept placeholder arguments.`,
@@ -166,3 +165,43 @@ func aliasList(cmd *cobra.Command, args []string) error {
166165

167166
return tp.Render()
168167
}
168+
169+
var aliasDeleteCmd = &cobra.Command{
170+
Use: "delete <alias>",
171+
Short: "Delete an alias.",
172+
Args: cobra.ExactArgs(1),
173+
Example: "gh alias delete co",
174+
RunE: aliasDelete,
175+
}
176+
177+
func aliasDelete(cmd *cobra.Command, args []string) error {
178+
alias := args[0]
179+
180+
ctx := contextForCommand(cmd)
181+
cfg, err := ctx.Config()
182+
if err != nil {
183+
return fmt.Errorf("couldn't read config: %w", err)
184+
}
185+
186+
aliasCfg, err := cfg.Aliases()
187+
if err != nil {
188+
return fmt.Errorf("couldn't read aliases config: %w", err)
189+
}
190+
191+
if !aliasCfg.Exists(alias) {
192+
return fmt.Errorf("no such alias %s", alias)
193+
}
194+
195+
expansion := aliasCfg.Get(alias)
196+
197+
err = aliasCfg.Delete(alias)
198+
if err != nil {
199+
return fmt.Errorf("failed to delete alias %s: %w", alias, err)
200+
}
201+
202+
out := colorableOut(cmd)
203+
redCheck := utils.Red("✓")
204+
fmt.Fprintf(out, "%s Deleted alias %s; was %s\n", redCheck, alias, expansion)
205+
206+
return nil
207+
}

command/alias_test.go

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,6 @@ aliases:
183183

184184
func TestExpandAlias(t *testing.T) {
185185
cfg := `---
186-
hosts:
187-
github.com:
188-
user: OWNER
189-
oauth_token: token123
190186
aliases:
191187
co: pr checkout
192188
il: issue list --author="$1" --label="$2"
@@ -266,11 +262,9 @@ aliases:
266262
initBlankContext(cfg, "OWNER/REPO", "trunk")
267263

268264
output, err := RunCommand("alias list")
269-
270265
if err != nil {
271266
t.Fatalf("unexpected error: %s", err)
272267
}
273-
274268
expected := `clone repo clone
275269
co pr checkout
276270
cs config set editor 'quoted path'
@@ -280,3 +274,48 @@ prs pr status
280274

281275
eq(t, output.String(), expected)
282276
}
277+
278+
func TestAliasDelete_nonexistent_command(t *testing.T) {
279+
cfg := `---
280+
aliases:
281+
co: pr checkout
282+
il: issue list --author="$1" --label="$2"
283+
ia: issue list --author="$1" --assignee="$1"
284+
`
285+
initBlankContext(cfg, "OWNER/REPO", "trunk")
286+
287+
_, err := RunCommand("alias delete cool")
288+
if err == nil {
289+
t.Fatalf("expected error")
290+
}
291+
292+
eq(t, err.Error(), "no such alias cool")
293+
}
294+
295+
func TestAliasDelete(t *testing.T) {
296+
cfg := `---
297+
aliases:
298+
co: pr checkout
299+
il: issue list --author="$1" --label="$2"
300+
ia: issue list --author="$1" --assignee="$1"
301+
`
302+
initBlankContext(cfg, "OWNER/REPO", "trunk")
303+
304+
mainBuf := bytes.Buffer{}
305+
hostsBuf := bytes.Buffer{}
306+
defer config.StubWriteConfig(&mainBuf, &hostsBuf)()
307+
308+
output, err := RunCommand("alias delete co")
309+
if err != nil {
310+
t.Fatalf("unexpected error: %s", err)
311+
}
312+
313+
test.ExpectLines(t, output.String(), "Deleted alias co; was pr checkout")
314+
315+
expected := `aliases:
316+
il: issue list --author="$1" --label="$2"
317+
ia: issue list --author="$1" --assignee="$1"
318+
`
319+
320+
eq(t, mainBuf.String(), expected)
321+
}

internal/config/alias_config.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ func (a *AliasConfig) Add(alias, expansion string) error {
3939
}
4040

4141
func (a *AliasConfig) Delete(alias string) error {
42-
// TODO when we get to gh alias delete
42+
a.RemoveEntry(alias)
43+
44+
err := a.Parent.Write()
45+
if err != nil {
46+
return fmt.Errorf("failed to write config: %w", err)
47+
}
48+
4349
return nil
4450
}
4551

internal/config/config_type.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,21 @@ func (cm *ConfigMap) FindEntry(key string) (ce *ConfigEntry, err error) {
100100
return ce, &NotFoundError{errors.New("not found")}
101101
}
102102

103+
func (cm *ConfigMap) RemoveEntry(key string) {
104+
newContent := []*yaml.Node{}
105+
106+
content := cm.Root.Content
107+
for i := 0; i < len(content); i++ {
108+
if content[i].Value == key {
109+
i++ // skip the next node which is this key's value
110+
} else {
111+
newContent = append(newContent, content[i])
112+
}
113+
}
114+
115+
cm.Root.Content = newContent
116+
}
117+
103118
func NewConfig(root *yaml.Node) Config {
104119
return &fileConfig{
105120
ConfigMap: ConfigMap{Root: root.Content[0]},

0 commit comments

Comments
 (0)