mirror of
https://github.com/gopasspw/gopass.git
synced 2026-09-29 11:12:40 +02:00
* Add storage.TryAdd and TryCommit methods Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org> * Fix lint errors and replace Git with Fossil in the Fossil backend. Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org> --------- Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>
159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
package leaf
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/gopasspw/gopass/internal/out"
|
|
"github.com/gopasspw/gopass/internal/store"
|
|
"github.com/gopasspw/gopass/internal/tree"
|
|
"github.com/gopasspw/gopass/pkg/ctxutil"
|
|
"github.com/gopasspw/gopass/pkg/debug"
|
|
)
|
|
|
|
const (
|
|
// TemplateFile is the name of a pass template.
|
|
TemplateFile = ".pass-template"
|
|
)
|
|
|
|
// LookupTemplate will lookup and return a template.
|
|
func (s *Store) LookupTemplate(ctx context.Context, name string) (string, []byte, bool) {
|
|
oName := name
|
|
// go upwards in the directory tree until we find a template
|
|
// by chopping off one path element by one.
|
|
for {
|
|
l1 := len(name)
|
|
name = filepath.Dir(name)
|
|
|
|
if len(name) == l1 {
|
|
break
|
|
}
|
|
|
|
tpl := filepath.Join(name, TemplateFile)
|
|
|
|
if s.storage.Exists(ctx, tpl) {
|
|
if content, err := s.storage.Get(ctx, tpl); err == nil {
|
|
debug.Log("Found template %q for %q", tpl, oName)
|
|
|
|
return tpl, content, true
|
|
}
|
|
}
|
|
}
|
|
|
|
return "", []byte{}, false
|
|
}
|
|
|
|
// ListTemplates will list all templates in this store.
|
|
func (s *Store) ListTemplates(ctx context.Context, prefix string) []string {
|
|
lst, err := s.storage.List(ctx, "")
|
|
if err != nil {
|
|
debug.Log("failed to list templates: %s", err)
|
|
|
|
return nil
|
|
}
|
|
|
|
tpls := make(map[string]struct{}, len(lst))
|
|
|
|
for _, path := range lst {
|
|
if !strings.HasSuffix(path, TemplateFile) {
|
|
continue
|
|
}
|
|
|
|
path = strings.TrimSuffix(path, Sep+TemplateFile)
|
|
|
|
if prefix != "" {
|
|
path = prefix + Sep + path
|
|
}
|
|
|
|
tpls[path] = struct{}{}
|
|
}
|
|
|
|
out := make([]string, 0, len(tpls))
|
|
|
|
for k := range tpls {
|
|
out = append(out, k)
|
|
}
|
|
|
|
sort.Strings(out)
|
|
|
|
return out
|
|
}
|
|
|
|
// TemplateTree returns a tree of all templates.
|
|
func (s *Store) TemplateTree(ctx context.Context) *tree.Root {
|
|
root := tree.New("gopass")
|
|
|
|
for _, t := range s.ListTemplates(ctx, "") {
|
|
if err := root.AddFile(t, "gopass/template"); err != nil {
|
|
out.Errorf(ctx, "Failed to add template: %s", err)
|
|
}
|
|
}
|
|
|
|
return root
|
|
}
|
|
|
|
// templatefile returns the name of the given template on disk.
|
|
func (s *Store) templatefile(name string) string {
|
|
return strings.TrimPrefix(filepath.Join(name, TemplateFile), string(filepath.Separator))
|
|
}
|
|
|
|
// HasTemplate returns true if the template exists.
|
|
func (s *Store) HasTemplate(ctx context.Context, name string) bool {
|
|
return s.storage.Exists(ctx, s.templatefile(name))
|
|
}
|
|
|
|
// GetTemplate will return the content of the named template.
|
|
func (s *Store) GetTemplate(ctx context.Context, name string) ([]byte, error) {
|
|
return s.storage.Get(ctx, s.templatefile(name))
|
|
}
|
|
|
|
// SetTemplate will (over)write the content to the template file.
|
|
func (s *Store) SetTemplate(ctx context.Context, name string, content []byte) error {
|
|
p := s.templatefile(name)
|
|
|
|
if err := s.storage.Set(ctx, p, content); err != nil {
|
|
if errors.Is(err, store.ErrMeaninglessWrite) {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("failed to write template: %w", err)
|
|
}
|
|
|
|
if err := s.storage.TryAdd(ctx, p); err != nil {
|
|
return fmt.Errorf("failed to add %q to git: %w", p, err)
|
|
}
|
|
|
|
if !ctxutil.IsGitCommit(ctx) {
|
|
return nil
|
|
}
|
|
|
|
return s.gitCommitAndPush(ctx, name)
|
|
}
|
|
|
|
// RemoveTemplate will delete the named template if it exists.
|
|
func (s *Store) RemoveTemplate(ctx context.Context, name string) error {
|
|
p := s.templatefile(name)
|
|
|
|
if err := s.storage.Delete(ctx, p); err != nil {
|
|
return fmt.Errorf("failed to remote template: %w", err)
|
|
}
|
|
|
|
if err := s.storage.Add(ctx, p); err != nil {
|
|
if errors.Is(err, store.ErrGitNotInit) {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("failed to add %q to git: %w", p, err)
|
|
}
|
|
|
|
if !ctxutil.IsGitCommit(ctx) {
|
|
return nil
|
|
}
|
|
|
|
return s.gitCommitAndPush(ctx, name)
|
|
}
|