func (g *Git) IsInitialized() bool {
	return fsutil.IsFile(filepath.Join(g.fs.Path(), ".git", "config"))
}
IsInitialized returns true if this stores has an (probably) initialized .git folder
package gitfs
import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"github.com/gopasspw/gopass/internal/backend"
	"github.com/gopasspw/gopass/internal/backend/storage/fs"
	"github.com/gopasspw/gopass/internal/out"
	"github.com/gopasspw/gopass/internal/store"
	"github.com/gopasspw/gopass/pkg/ctxutil"
	"github.com/gopasspw/gopass/pkg/debug"
	"github.com/gopasspw/gopass/pkg/fsutil"
	"github.com/blang/semver/v4"
)
type contextKey int
const (
	ctxKeyPathOverride contextKey = iota
)
func withPathOverride(ctx context.Context, path string) context.Context {
	return context.WithValue(ctx, ctxKeyPathOverride, path)
}
func getPathOverride(ctx context.Context, def string) string {
	if sv, ok := ctx.Value(ctxKeyPathOverride).(string); ok && sv != "" {
		return sv
	}
	return def
}
type Git struct {
	fs *fs.Store
}
func New(path string) (*Git, error) {
	if !fsutil.IsDir(filepath.Join(path, ".git")) {
		return nil, fmt.Errorf("git repo does not exist")
	}
	return &Git{
		fs: fs.New(path),
	}, nil
}
func Clone(ctx context.Context, repo, path string) (*Git, error) {
	g := &Git{
		fs: fs.New(path),
	}
	if err := g.Cmd(withPathOverride(ctx, filepath.Dir(path)), "Clone", "clone", repo, path); err != nil {
		return nil, err
	}
	return g, nil
}
func Init(ctx context.Context, path, userName, userEmail string) (*Git, error) {
	g := &Git{
		fs: fs.New(path),
	}
	if !g.IsInitialized() {
		if err := g.Cmd(ctx, "Init", "init"); err != nil {
			return nil, fmt.Errorf("failed to initialize git: %s", err)
		}
		out.Printf(ctx, "git initialized at %s", g.fs.Path())
	}
	if !ctxutil.IsGitInit(ctx) {
		return g, nil
	}
	if err := g.InitConfig(ctx, userName, userEmail); err != nil {
		return g, fmt.Errorf("failed to configure git: %s", err)
	}
	out.Printf(ctx, "git configured at %s", g.fs.Path())
	if err := g.Add(ctx, g.fs.Path()); err != nil {
		return g, fmt.Errorf("failed to add %q to git: %w", g.fs.Path(), err)
	}
	if !g.HasStagedChanges(ctx) {
		debug.Log("No staged changes")
		return g, nil
	}
	if err := g.Commit(ctx, "Add current content of password store"); err != nil {
		return g, fmt.Errorf("failed to commit changes to git: %w", err)
	}
	return g, nil
}
func (g *Git) captureCmd(ctx context.Context, name string, args ...string) ([]byte, []byte, error) {
	bufOut := &bytes.Buffer{}
	bufErr := &bytes.Buffer{}
	cmd := exec.CommandContext(ctx, "git", args[0:]...)
	cmd.Dir = getPathOverride(ctx, g.fs.Path())
	cmd.Stdout = bufOut
	cmd.Stderr = bufErr
	if debug.IsEnabled() && ctxutil.IsVerbose(ctx) {
		cmd.Stdout = io.MultiWriter(bufOut, os.Stdout)
		cmd.Stderr = io.MultiWriter(bufErr, os.Stderr)
	}
	debug.Log("store.%s: %s %+v (%s)", name, cmd.Path, cmd.Args, g.fs.Path())
	err := cmd.Run()
	return bufOut.Bytes(), bufErr.Bytes(), err
}
func (g *Git) Cmd(ctx context.Context, name string, args ...string) error {
	stdout, stderr, err := g.captureCmd(ctx, name, args...)
	if err != nil {
		debug.Log("CMD: %s %+v\nError: %s\nOutput:\n  Stdout: %q\n  Stderr: %q", name, args, err, string(stdout), string(stderr))
		return fmt.Errorf("%s: %s", err, strings.TrimSpace(string(stderr)))
	}
	return nil
}
func (g *Git) Name() string {
	return "git"
}
func (g *Git) Version(ctx context.Context) semver.Version {
	v := semver.Version{}
	cmd := exec.CommandContext(ctx, "git", "version")
	cmdout, err := cmd.Output()
	if err != nil {
		debug.Log("Failed to run 'git version': %s", err)
		return v
	}
	svStr := strings.TrimPrefix(string(cmdout), "git version ")
	if p := strings.Fields(svStr); len(p) > 0 {
		svStr = p[0]
	}
	sv, err := semver.ParseTolerant(svStr)
	if err != nil {
		debug.Log("Failed to parse %q as semver: %s", svStr, err)
		return v
	}
	return sv
}