From f28e2cdef271977f3ccf267342678d3b28ae5000 Mon Sep 17 00:00:00 2001 From: Peter Sanford Date: Sun, 22 Sep 2019 16:37:12 -0700 Subject: [PATCH] Fix password store to handle keys with '/' in them Previously the password store implementation assumed that all the keys lived directly in the prefix directory. This change fixes Keys() to also return keys that exist in a subdirectory. --- pass.go | 23 +++++++++++++---------- pass_test.go | 34 ++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/pass.go b/pass.go index fe2b11b..bfe796c 100644 --- a/pass.go +++ b/pass.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -142,16 +141,20 @@ func (k *passKeyring) Keys() ([]string, error) { return keys, fmt.Errorf("%s is not a directory", path) } - files, err := ioutil.ReadDir(path) - if err != nil { - return keys, err - } + err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error { + if err != nil { + return err + } - for _, f := range files { - if filepath.Ext(f.Name()) == ".gpg" { - name := filepath.Base(f.Name()) + if !info.IsDir() && filepath.Ext(p) == ".gpg" { + name := strings.TrimPrefix(p, path) + if name[0] == os.PathSeparator { + name = name[1:] + } keys = append(keys, name[:len(name)-4]) } - } - return keys, nil + return nil + }) + + return keys, err } diff --git a/pass_test.go b/pass_test.go index f631cb3..2573799 100644 --- a/pass_test.go +++ b/pass_test.go @@ -6,7 +6,7 @@ import ( "os" "os/exec" "path/filepath" - "sort" + "reflect" "testing" ) @@ -101,16 +101,16 @@ func TestPassKeyringKeysWhenNotEmpty(t *testing.T) { k, teardown := setup(t) defer teardown(t) - item := Item{Key: "llamas", Data: []byte("llamas are great")} - - if err := k.Set(item); err != nil { - t.Fatal(err) + items := []Item{ + {Key: "llamas", Data: []byte("llamas are great")}, + {Key: "alpacas", Data: []byte("alpacas are better")}, + {Key: "africa/elephants", Data: []byte("who doesn't like elephants")}, } - item = Item{Key: "alpacas", Data: []byte("alpacas are better")} - - if err := k.Set(item); err != nil { - t.Fatal(err) + for _, item := range items { + if err := k.Set(item); err != nil { + t.Fatal(err) + } } keys, err := k.Keys() @@ -118,16 +118,18 @@ func TestPassKeyringKeysWhenNotEmpty(t *testing.T) { t.Fatal(err) } - if len(keys) != 2 { - t.Fatalf("Expected 2 keys, got %d", len(keys)) + if len(keys) != len(items) { + t.Fatalf("Expected %d keys, got %d", len(items), len(keys)) } - sort.Strings(keys) - if keys[0] != "alpacas" { - t.Fatalf("Expected alpacas") + expectedKeys := []string{ + "africa/elephants", + "alpacas", + "llamas", } - if keys[1] != "llamas" { - t.Fatalf("Expected llamas") + + if !reflect.DeepEqual(keys, expectedKeys) { + t.Fatalf("Expected keys %v, got %v", expectedKeys, keys) } }