1package root
2
3import (
4	"context"
5	"fmt"
6
7	"github.com/gopasspw/gopass/internal/backend"
8	"github.com/gopasspw/gopass/internal/out"
9	"github.com/gopasspw/gopass/internal/store/leaf"
10	"github.com/gopasspw/gopass/pkg/debug"
11	"github.com/gopasspw/gopass/pkg/fsutil"
12)
13
14// IsInitialized checks on disk if .gpg-id was generated and thus returns true.
15func (r *Store) IsInitialized(ctx context.Context) (bool, error) {
16	if r.store == nil {
17		debug.Log("initializing store and possible sub-stores")
18		if err := r.initialize(ctx); err != nil {
19			return false, fmt.Errorf("failed to initialize stores: %w", err)
20		}
21	}
22	return r.store.IsInitialized(ctx), nil
23}
24
25// Init tries to initialize a new password store location matching the object
26func (r *Store) Init(ctx context.Context, alias, path string, ids ...string) error {
27	debug.Log("Instantiating new sub store %s at %s for %+v", alias, path, ids)
28	if !backend.HasCryptoBackend(ctx) {
29		ctx = backend.WithCryptoBackend(ctx, backend.GPGCLI)
30	}
31	if !backend.HasStorageBackend(ctx) {
32		ctx = backend.WithStorageBackend(ctx, backend.GitFS)
33	}
34	sub, err := leaf.New(ctx, alias, path)
35	if err != nil {
36		return fmt.Errorf("failed to instantiate new sub store: %w", err)
37	}
38	if !r.store.IsInitialized(ctx) && alias == "" {
39		r.store = sub
40	}
41
42	debug.Log("Initializing sub store at %s for %+v", path, ids)
43	if err := sub.Init(ctx, path, ids...); err != nil {
44		return fmt.Errorf("failed to initialize new sub store: %w", err)
45	}
46
47	if alias == "" {
48		debug.Log("initialized root at %s", path)
49		r.cfg.Path = path
50	} else {
51		debug.Log("mounted %s at %s", alias, path)
52		r.cfg.Mounts[alias] = path
53	}
54
55	return nil
56}
57
58func (r *Store) initialize(ctx context.Context) error {
59	// already initialized?
60	if r.store != nil {
61		return nil
62	}
63
64	// create the base store
65	path := fsutil.CleanPath(r.cfg.Path)
66	debug.Log("initialize - %s", path)
67	s, err := leaf.New(ctx, "", path)
68	if err != nil {
69		return fmt.Errorf("failed to initialize the root store at %q: %w", r.cfg.Path, err)
70	}
71	debug.Log("Root Store initialized at %s", path)
72	r.store = s
73
74	// initialize all mounts
75	for alias, path := range r.cfg.Mounts {
76		path := fsutil.CleanPath(path)
77		if err := r.addMount(ctx, alias, path); err != nil {
78			out.Errorf(ctx, "Failed to initialize mount %s (%s). Ignoring: %s", alias, path, err)
79			continue
80		}
81		debug.Log("Sub-Store mounted at %s from %s", alias, path)
82	}
83
84	// check for duplicate mounts
85	if err := r.checkMounts(); err != nil {
86		return fmt.Errorf("checking mounts failed: %w", err)
87	}
88
89	return nil
90}
91