commit 78dc2586b9103f6ef0cf522cfa784fb75940aa75
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-06-18T23:03:48Z |
| subject | daemon to support --v=2 |
commit 78dc2586b9103f6ef0cf522cfa784fb75940aa75
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-06-18T23:03:48Z
daemon to support --v=2
---
Makefile | 2 +-
cmd/flatgit/main.go | 35 ++++++++++++++++++++-----
internal/buildinfo/buildinfo_gen.go | 4 +--
internal/gitcmd/gitcmd.go | 51 ++++++++++++++++++++++++++++++++++---
4 files changed, 78 insertions(+), 14 deletions(-)
diff --git a/Makefile b/Makefile
index 213aaf3..ebcb615 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,7 @@ fmt:
gofmt -w ./cmd ./internal
run: build
- $(BIN_DIR)/flatgit daemon -c examples/tinyproxy.json
+ $(BIN_DIR)/flatgit daemon -c examples/tinyproxy.json --v=2
vet:
go vet ./...
diff --git a/cmd/flatgit/main.go b/cmd/flatgit/main.go
index d0b141d..b290789 100644
--- a/cmd/flatgit/main.go
+++ b/cmd/flatgit/main.go
@@ -22,14 +22,33 @@ import (
)
func main() {
- log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{}))
- if err := run(log, os.Args); err != nil {
+ var level slog.LevelVar
+ level.Set(slog.LevelInfo)
+
+ log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
+ Level: &level,
+ }))
+
+ if err := run(log, &level, os.Args); err != nil {
log.Error("flatgit failed", "err", err)
os.Exit(1)
}
}
-func run(log *slog.Logger, args []string) error {
+func applyVerbosity(level *slog.LevelVar, v int) {
+ if v >= 1 {
+ level.Set(slog.LevelDebug)
+ return
+ }
+
+ level.Set(slog.LevelInfo)
+}
+
+func addCommonFlags(fs *flag.FlagSet) *int {
+ return fs.Int("v", 0, "verbosity level")
+}
+
+func run(log *slog.Logger, level *slog.LevelVar, args []string) error {
if len(args) < 2 {
usage(args[0])
return errors.New("missing command")
@@ -41,7 +60,7 @@ func run(log *slog.Logger, args []string) error {
case "serve":
return serveCmd(log, args[2:])
case "daemon":
- return daemonCmd(log, args[2:])
+ return daemonCmd(log, level, args[2:])
case "version", "-v", "--version":
fmt.Printf("%s (%s)\n", buildinfo.Version, buildinfo.Timestamp)
return nil
@@ -99,13 +118,15 @@ func serveCmd(log *slog.Logger, args []string) error {
return server.ListenAndServe(ctx, server.Options{Addr: *addr, Root: *root, Logger: log})
}
-func daemonCmd(log *slog.Logger, args []string) error {
+func daemonCmd(log *slog.Logger, level *slog.LevelVar, args []string) error {
fs := flag.NewFlagSet("daemon", flag.ExitOnError)
cfgPath := fs.String("c", "flatgit.json", "config file")
+ v := addCommonFlags(fs)
renderOnStart := fs.Bool("render-on-start", true, "render all repos on startup")
if err := fs.Parse(args); err != nil {
return err
}
+ applyVerbosity(level, *v)
cfg, err := config.Load(*cfgPath)
if err != nil {
return err
@@ -114,7 +135,7 @@ func daemonCmd(log *slog.Logger, args []string) error {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
- git := gitcmd.New(cfg.Git.Command)
+ git := gitcmd.New(cfg.Git.Command, log)
r := render.New(git, cfg.PublicURL, cfg.Render.MaxCommits)
q := jobqueue.New(1024, log)
q.Start(ctx, cfg.Render.Workers, func(ctx context.Context, name string) error {
@@ -162,7 +183,7 @@ func repoMatches(repo config.Repo, name string) bool {
}
func renderConfigured(ctx context.Context, log *slog.Logger, cfg *config.Config, repoName string, fetch bool) error {
- git := gitcmd.New(cfg.Git.Command)
+ git := gitcmd.New(cfg.Git.Command, log)
r := render.New(git, cfg.PublicURL, cfg.Render.MaxCommits)
matched := false
diff --git a/internal/buildinfo/buildinfo_gen.go b/internal/buildinfo/buildinfo_gen.go
index 89801d4..d079abc 100644
--- a/internal/buildinfo/buildinfo_gen.go
+++ b/internal/buildinfo/buildinfo_gen.go
@@ -2,6 +2,6 @@ package buildinfo
const (
Version = "dev"
- GitRevision = "ae2ca700755df37c186d45857ad98648ad940781"
- Timestamp = "20260618.222654"
+ GitRevision = "34bbedf22eec0a64eafd23241d4225cbfe8fc707"
+ Timestamp = "20260618.230137"
)
diff --git a/internal/gitcmd/gitcmd.go b/internal/gitcmd/gitcmd.go
index c1beb75..34606d4 100644
--- a/internal/gitcmd/gitcmd.go
+++ b/internal/gitcmd/gitcmd.go
@@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
+ "log/slog"
"os"
"os/exec"
"path/filepath"
@@ -16,13 +17,17 @@ import (
type Runner struct {
GitCommand string
+ Logger *slog.Logger
}
-func New(command string) *Runner {
- if command == "" {
- command = "git"
+func New(gitCommand string, logger *slog.Logger) *Runner {
+ if gitCommand == "" {
+ gitCommand = "git"
+ }
+ return &Runner{
+ GitCommand: gitCommand,
+ Logger: logger,
}
- return &Runner{GitCommand: command}
}
func (r *Runner) EnsureMirror(ctx context.Context, repo config.Repo, cloneTimeout, fetchTimeout time.Duration) error {
@@ -69,19 +74,57 @@ func (r *Runner) EnsureMirror(ctx context.Context, repo config.Repo, cloneTimeou
func (r *Runner) Output(ctx context.Context, dir string, args ...string) ([]byte, error) {
cmd := exec.CommandContext(ctx, r.GitCommand, args...)
cmd.Env = os.Environ()
+
if dir != "" {
cmd.Dir = dir
}
+
+ if r.Logger != nil {
+ r.Logger.Debug("git command started",
+ "dir", cmd.Dir,
+ "cmd", r.GitCommand,
+ "args", args,
+ )
+ }
+
+ start := time.Now()
+
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
+
if err := cmd.Run(); err != nil {
+ dur := time.Since(start)
msg := strings.TrimSpace(stderr.String())
if msg == "" {
msg = err.Error()
}
+
+ if r.Logger != nil {
+ r.Logger.Warn("git command failed",
+ "dir", cmd.Dir,
+ "cmd", r.GitCommand,
+ "args", args,
+ "dur", dur,
+ "stdout_bytes", stdout.Len(),
+ "stderr", msg,
+ )
+ }
+
return stdout.Bytes(), fmt.Errorf("git %s: %s", strings.Join(args, " "), msg)
}
+
+ if r.Logger != nil {
+ r.Logger.Debug("git command finished",
+ "dir", cmd.Dir,
+ "cmd", r.GitCommand,
+ "args", args,
+ "dur", time.Since(start),
+ "stdout_bytes", stdout.Len(),
+ "stderr_bytes", stderr.Len(),
+ )
+ }
+
return stdout.Bytes(), nil
}