penguin/flatgit

flatgit showcase

commit 9cb44b0041b3e0d5a7afcc9f26621cc19606bdfa

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-06-28T02:42:49Z
subjectAdded liveness test
commit 9cb44b0041b3e0d5a7afcc9f26621cc19606bdfa
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-06-28T02:42:49Z

    Added liveness test
---
 internal/buildinfo/buildinfo_gen.go |  4 +--
 internal/gitcmd/gitcmd.go           | 49 +++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/internal/buildinfo/buildinfo_gen.go b/internal/buildinfo/buildinfo_gen.go
index 9cc9af0..e1638c8 100644
--- a/internal/buildinfo/buildinfo_gen.go
+++ b/internal/buildinfo/buildinfo_gen.go
@@ -2,6 +2,6 @@ package buildinfo
 
 const (
     Version     = "dev"
-    GitRevision = "5ce6c3b70b12fb55cf0e108c7eabc51d5c50ae43"
-    Timestamp   = "20260627.005304"
+    GitRevision = "c152a522ff4215c0dcc176118c4997f7f79fe770"
+    Timestamp   = "20260628.023834"
 )
diff --git a/internal/gitcmd/gitcmd.go b/internal/gitcmd/gitcmd.go
index 34606d4..bb185f5 100644
--- a/internal/gitcmd/gitcmd.go
+++ b/internal/gitcmd/gitcmd.go
@@ -30,10 +30,51 @@ func New(gitCommand string, logger *slog.Logger) *Runner {
 	}
 }
 
+func (r *Runner) waitRemoteLive(ctx context.Context, url string, timeout time.Duration) error {
+	const attempts = 5
+
+	backoff := 500 * time.Millisecond
+
+	var lastErr error
+
+	for i := 0; i < attempts; i++ {
+		probeCtx, cancel := context.WithTimeout(ctx, timeout)
+
+		_, err := r.Output(probeCtx, "", "ls-remote", "--heads", url)
+
+		cancel()
+
+		if err == nil {
+			return nil
+		}
+
+		lastErr = err
+
+		if i == attempts-1 {
+			break
+		}
+
+		select {
+		case <-ctx.Done():
+			return ctx.Err()
+		case <-time.After(backoff):
+		}
+
+		backoff *= 2
+	}
+
+	return lastErr
+}
+
 func (r *Runner) EnsureMirror(ctx context.Context, repo config.Repo, cloneTimeout, fetchTimeout time.Duration) error {
 	if repo.URL == "" {
 		return fmt.Errorf("repo %s has no url", repo.FullName())
 	}
+
+	if err := r.waitRemoteLive(ctx, repo.URL, fetchTimeout); err != nil {
+		return fmt.Errorf("repo %s remote not reachable: %w", repo.FullName(), err)
+	}
+
 	lockPath := repo.MirrorDir + ".lock"
 	unlock, err := acquireLock(lockPath)
 	if err != nil {
@@ -44,10 +85,12 @@ func (r *Runner) EnsureMirror(ctx context.Context, repo config.Repo, cloneTimeou
 	if isGitDir(repo.MirrorDir) {
 		ctx, cancel := context.WithTimeout(ctx, fetchTimeout)
 		defer cancel()
+
 		_, err := r.Output(ctx, repo.MirrorDir, "remote", "update", "--prune")
 		if err != nil {
 			return err
 		}
+
 		_, _ = r.Output(context.Background(), repo.MirrorDir, "pack-refs", "--all", "--prune")
 		return nil
 	}
@@ -55,19 +98,25 @@ func (r *Runner) EnsureMirror(ctx context.Context, repo config.Repo, cloneTimeou
 	if err := os.MkdirAll(filepath.Dir(repo.MirrorDir), 0o755); err != nil {
 		return err
 	}
+
 	tmp := repo.MirrorDir + ".tmp"
 	_ = os.RemoveAll(tmp)
+
 	ctx, cancel := context.WithTimeout(ctx, cloneTimeout)
 	defer cancel()
+
 	if _, err := r.Output(ctx, "", "clone", "--mirror", repo.URL, tmp); err != nil {
 		_ = os.RemoveAll(tmp)
 		return err
 	}
+
 	_ = os.RemoveAll(repo.MirrorDir)
+
 	if err := os.Rename(tmp, repo.MirrorDir); err != nil {
 		_ = os.RemoveAll(tmp)
 		return err
 	}
+
 	return nil
 }