From 243886edc8a6f88a589f6870b4365f78e107951a Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 29 Oct 2014 17:42:21 -0700 Subject: [PATCH] etcdctl: add -p to ls command This is a port of coreos/etcdctl#96 --- etcdctl/README.md | 7 +++++++ etcdctl/command/handle.go | 14 ++++++++++++++ etcdctl/command/ls_command.go | 19 +++++++++++++------ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/etcdctl/README.md b/etcdctl/README.md index 027b779a7..73bfc86b1 100644 --- a/etcdctl/README.md +++ b/etcdctl/README.md @@ -127,6 +127,13 @@ $ etcdctl ls --recursive /adir/key2 ``` +Directories can also have a trailing `/` added to output using `-p`. + +``` +$ etcdctl ls -p +/akey +/adir/ +``` ### Deleting a key diff --git a/etcdctl/command/handle.go b/etcdctl/command/handle.go index 7e1f981d3..d8b70759b 100644 --- a/etcdctl/command/handle.go +++ b/etcdctl/command/handle.go @@ -14,6 +14,7 @@ import ( type handlerFunc func(*cli.Context, *etcd.Client) (*etcd.Response, error) type printFunc func(*etcd.Response, string) +type contextualPrintFunc func(*cli.Context, *etcd.Response, string) // dumpCURL blindly dumps all curl output to os.Stderr func dumpCURL(client *etcd.Client) { @@ -106,6 +107,19 @@ func handlePrint(c *cli.Context, fn handlerFunc, pFn printFunc) { } } +// Just like handlePrint but also passed the context of the command +func handleContextualPrint(c *cli.Context, fn handlerFunc, pFn contextualPrintFunc) { + resp, err := rawhandle(c, fn) + + if err != nil { + handleError(ErrorFromEtcd, err) + } + + if resp != nil && pFn != nil { + pFn(c, resp, c.GlobalString("output")) + } +} + // handleDir handles a request that wants to do operations on a single dir. // Dir cannot be printed out, so we set NIL print function here. func handleDir(c *cli.Context, fn handlerFunc) { diff --git a/etcdctl/command/ls_command.go b/etcdctl/command/ls_command.go index 7f15fd718..9b83a662c 100644 --- a/etcdctl/command/ls_command.go +++ b/etcdctl/command/ls_command.go @@ -13,6 +13,7 @@ func NewLsCommand() cli.Command { Usage: "retrieve a directory", Flags: []cli.Flag{ cli.BoolFlag{Name: "recursive", Usage: "returns all values for key and child keys"}, + cli.BoolFlag{Name: "p", Usage: "append slash (/) to directories"}, }, Action: func(c *cli.Context) { handleLs(c, lsCommandFunc) @@ -22,17 +23,17 @@ func NewLsCommand() cli.Command { // handleLs handles a request that intends to do ls-like operations. func handleLs(c *cli.Context, fn handlerFunc) { - handlePrint(c, fn, printLs) + handleContextualPrint(c, fn, printLs) } // printLs writes a response out in a manner similar to the `ls` command in unix. // Non-empty directories list their contents and files list their name. -func printLs(resp *etcd.Response, format string) { +func printLs(c *cli.Context, resp *etcd.Response, format string) { if !resp.Node.Dir { fmt.Println(resp.Node.Key) } for _, node := range resp.Node.Nodes { - rPrint(node) + rPrint(c, node) } } @@ -49,9 +50,15 @@ func lsCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) } // rPrint recursively prints out the nodes in the node structure. -func rPrint(n *etcd.Node) { - fmt.Println(n.Key) +func rPrint(c *cli.Context, n *etcd.Node) { + + if n.Dir && c.Bool("p") { + fmt.Println(fmt.Sprintf("%v/", n.Key)) + } else { + fmt.Println(n.Key) + } + for _, node := range n.Nodes { - rPrint(node) + rPrint(c, node) } }