Skip to content

Commit

Permalink
Split root and sub store packages (gopasspw#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikschulz authored Jun 14, 2017
1 parent 776a767 commit 8e31f46
Show file tree
Hide file tree
Showing 42 changed files with 1,567 additions and 1,185 deletions.
81 changes: 29 additions & 52 deletions action/action.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package action

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"golang.org/x/crypto/ssh/terminal"

"github.com/fatih/color"
"github.com/ghodss/yaml"
"github.com/justwatchcom/gopass/config"
"github.com/justwatchcom/gopass/fsutil"
"github.com/justwatchcom/gopass/gpg"
"github.com/justwatchcom/gopass/password"
"github.com/justwatchcom/gopass/store/root"
)

// Action knows everything to run gopass CLI actions
type Action struct {
Name string
Store *password.RootStore
Store *root.Store
}

// New returns a new Action wrapper
Expand All @@ -32,39 +30,40 @@ func New(v string) *Action {
if gdb := os.Getenv("GOPASS_DEBUG"); gdb == "true" {
gpg.Debug = true
}
pwDir := pwStoreDir("")

// try to read config (if it exists)
for _, l := range configLocations() {
if cfg, err := newFromFile(l); err == nil && cfg != nil {
cfg.ImportFunc = askForKeyImport
cfg.FsckFunc = askForConfirmation
cfg.Version = v
color.NoColor = cfg.NoColor
// need this override for our integration tests
if nc := os.Getenv("GOPASS_NOCOLOR"); nc == "true" {
color.NoColor = true
}
// only emit color codes when stdout is a terminal
if !terminal.IsTerminal(int(os.Stdout.Fd())) {
color.NoColor = true
}
return &Action{
Name: name,
Store: cfg,
}
if cfg, err := config.Load(); err == nil && cfg != nil {
cfg.ImportFunc = askForKeyImport
cfg.FsckFunc = askForConfirmation
cfg.Version = v
color.NoColor = cfg.NoColor
// need this override for our integration tests
if nc := os.Getenv("GOPASS_NOCOLOR"); nc == "true" {
color.NoColor = true
}
// only emit color codes when stdout is a terminal
if !terminal.IsTerminal(int(os.Stdout.Fd())) {
color.NoColor = true
}
store, err := root.New(cfg)
if err != nil {
panic(err)
}
return &Action{
Name: name,
Store: store,
}
}

cfg, err := password.NewRootStore(pwDir)
cfg := config.New()
cfg.Path = pwStoreDir("")
cfg.ImportFunc = askForKeyImport
cfg.FsckFunc = askForConfirmation
rs, err := root.New(cfg)
if err != nil {
panic(err)
}

cfg.ImportFunc = askForKeyImport
cfg.FsckFunc = askForConfirmation
cfg.Version = v
color.NoColor = cfg.NoColor
// need this override for our integration tests
if nc := os.Getenv("GOPASS_NOCOLOR"); nc == "true" {
color.NoColor = true
Expand All @@ -75,30 +74,8 @@ func New(v string) *Action {

return &Action{
Name: name,
Store: cfg,
}
}

// newFromFile creates a new RootStore instance by unmarsahling a config file.
// If the file doesn't exist or fails to unmarshal an error is returned
func newFromFile(cf string) (*password.RootStore, error) {
// deliberately using os.Stat here, a symlinked
// config is OK
if _, err := os.Stat(cf); err != nil {
return nil, err
}
buf, err := ioutil.ReadFile(cf)
if err != nil {
fmt.Printf("Error reading config from %s: %s\n", cf, err)
return nil, err
}
cfg := &password.RootStore{}
err = yaml.Unmarshal(buf, &cfg)
if err != nil {
fmt.Printf("Error reading config from %s: %s\n", cf, err)
return nil, err
Store: rs,
}
return cfg, nil
}

// String implement fmt.Stringer
Expand Down
2 changes: 1 addition & 1 deletion action/clihelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// confirmRecipients asks the user to confirm a given set of recipients
func (s *Action) confirmRecipients(name string, recipients []string) ([]string, error) {
if s.Store.NoConfirm {
if s.Store.NoConfirm() {
return recipients, nil
}
for {
Expand Down
2 changes: 1 addition & 1 deletion action/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (s *Action) Clone(c *cli.Context) error {
}

// save new mount in config file
if err := writeConfig(s.Store); err != nil {
if err := s.Store.Config().Save(); err != nil {
return fmt.Errorf("Failed to update config: %s", err)
}

Expand Down
2 changes: 1 addition & 1 deletion action/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (s *Action) CompletionDMenu(c *cli.Context) error {
return err
}

content, err := s.Store.First(name)
content, err := s.Store.GetFirstLine(name)
if err != nil {
return err
}
Expand Down
134 changes: 10 additions & 124 deletions action/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,8 @@ package action

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strconv"
"strings"

"github.com/ghodss/yaml"
"github.com/justwatchcom/gopass/fsutil"
"github.com/justwatchcom/gopass/password"
"github.com/urfave/cli"
)

Expand All @@ -34,33 +25,17 @@ func (s *Action) Config(c *cli.Context) error {
}

func (s *Action) printConfigValues(filter ...string) error {
out := make([]string, 0, 10)
o := reflect.ValueOf(s.Store).Elem()
for i := 0; i < o.NumField(); i++ {
jsonArg := o.Type().Field(i).Tag.Get("json")
if jsonArg == "" || jsonArg == "-" {
m := s.Store.Config().ConfigMap()
out := make([]string, 0, len(m))
for k := range m {
if !contains(filter, k) {
continue
}
if !contains(filter, jsonArg) {
continue
}
f := o.Field(i)
strVal := ""
switch f.Kind() {
case reflect.String:
strVal = f.String()
case reflect.Bool:
strVal = fmt.Sprintf("%t", f.Bool())
case reflect.Int:
strVal = fmt.Sprintf("%d", f.Int())
default:
continue
}
out = append(out, fmt.Sprintf("%s: %s", jsonArg, strVal))
out = append(out, k)
}
sort.Strings(out)
for _, line := range out {
fmt.Println(line)
for _, k := range out {
fmt.Printf("%s: %s\n", k, m[k])
}
return nil
}
Expand All @@ -78,98 +53,9 @@ func contains(haystack []string, needle string) bool {
}

func (s *Action) setConfigValue(key, value string) error {
if key == "version" {
return fmt.Errorf("Can not change version")
}
if key != "path" {
value = strings.ToLower(value)
}
o := reflect.ValueOf(s.Store).Elem()
for i := 0; i < o.NumField(); i++ {
jsonArg := o.Type().Field(i).Tag.Get("json")
if jsonArg == "" || jsonArg == "-" {
continue
}
if jsonArg != key {
continue
}
f := o.Field(i)
switch f.Kind() {
case reflect.String:
f.SetString(value)
case reflect.Bool:
if value == "true" {
f.SetBool(true)
} else if value == "false" {
f.SetBool(false)
} else {
return fmt.Errorf("No a bool: %s", value)
}
case reflect.Int:
iv, err := strconv.Atoi(value)
if err != nil {
return err
}
f.SetInt(int64(iv))
default:
continue
}
}
return writeConfig(s.Store)
}

// hasConfig is a short hand for checking if the config file exists
func hasConfig() bool {
for _, l := range configLocations() {
if fsutil.IsFile(l) {
return true
}
}
return false
}

// writeConfig saves the config
func writeConfig(s *password.RootStore) error {
buf, err := yaml.Marshal(s)
if err != nil {
cfg := s.Store.Config()
if err := cfg.SetConfigValue(key, value); err != nil {
return err
}
cfgLoc := configLocation()
cfgDir := filepath.Dir(cfgLoc)
if !fsutil.IsDir(cfgDir) {
if err := os.MkdirAll(cfgDir, 0700); err != nil {
return err
}
}
if err := ioutil.WriteFile(cfgLoc, buf, 0600); err != nil {
return err
}
return nil
}

// configLocation returns the location of the config file. Either reading from
// GOPASS_CONFIG or using the default location (~/.gopass.yml)
func configLocation() string {
if cf := os.Getenv("GOPASS_CONFIG"); cf != "" {
return cf
}
if xch := os.Getenv("XDG_CONFIG_HOME"); xch != "" {
return filepath.Join(xch, "gopass", "config.yml")
}
return filepath.Join(os.Getenv("HOME"), ".config", "gopass", "config.yml")
}

// configLocations returns the possible locations of gopass config files,
// in decreasing priority
func configLocations() []string {
l := []string{}
if cf := os.Getenv("GOPASS_CONFIG"); cf != "" {
l = append(l, cf)
}
if xch := os.Getenv("XDG_CONFIG_HOME"); xch != "" {
l = append(l, filepath.Join(xch, "gopass", "config.yml"))
}
l = append(l, filepath.Join(os.Getenv("HOME"), ".config", "gopass", "config.yml"))
l = append(l, filepath.Join(os.Getenv("HOME"), ".gopass.yml"))
return l
return s.Store.UpdateConfig(cfg)
}
4 changes: 2 additions & 2 deletions action/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package action
import (
"fmt"

"github.com/justwatchcom/gopass/password"
"github.com/justwatchcom/gopass/store"
"github.com/urfave/cli"
)

Expand All @@ -18,7 +18,7 @@ func (s *Action) Delete(c *cli.Context) error {
}

found, err := s.Store.Exists(name)
if err != nil && err != password.ErrNotFound {
if err != nil && err != store.ErrNotFound {
return fmt.Errorf("failed to see if %s exists", name)
}

Expand Down
4 changes: 2 additions & 2 deletions action/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"os/exec"

"github.com/justwatchcom/gopass/fsutil"
"github.com/justwatchcom/gopass/password"
"github.com/justwatchcom/gopass/pwgen"
"github.com/justwatchcom/gopass/store"
"github.com/justwatchcom/gopass/tpl"
shellquote "github.com/kballard/go-shellquote"
"github.com/urfave/cli"
Expand All @@ -24,7 +24,7 @@ func (s *Action) Edit(c *cli.Context) error {
}

exists, err := s.Store.Exists(name)
if err != nil && err != password.ErrNotFound {
if err != nil && err != store.ErrNotFound {
return fmt.Errorf("failed to see if %s exists", name)
}

Expand Down
6 changes: 4 additions & 2 deletions action/fsck.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ func (s *Action) Fsck(c *cli.Context) error {
force = false
}
// make sure config is in the right place
if err := writeConfig(s.Store); err != nil {
// we may have loaded it from one of the fallback locations
if err := s.Store.Config().Save(); err != nil {
return err
}
// clean up any previous config locations
Expand All @@ -27,5 +28,6 @@ func (s *Action) Fsck(c *cli.Context) error {
color.Red("Failed to remove old gopass config %s: %s", oldCfg, err)
}
}
return s.Store.Fsck(check, force)
_, err := s.Store.Fsck("", check, force)
return err
}
Loading

0 comments on commit 8e31f46

Please sign in to comment.