penguin/flatgit

flatgit showcase

commit 351aa29cde84023a850bad9d3ede7f44a18b85e3

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-07-04T13:01:36Z
subjectAdded render archive
commit 351aa29cde84023a850bad9d3ede7f44a18b85e3
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-07-04T13:01:36Z

    Added render archive
---
 README.md                           |  5 +---
 internal/buildinfo/buildinfo_gen.go |  4 ++--
 internal/render/archive.go          | 48 +++++++++++++++++++++++++++++++++++++
 internal/render/manifest.go         |  2 +-
 internal/render/render.go           |  4 ++++
 internal/render/templates.go        |  1 +
 6 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index c969624..9a1225f 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ HTML should be served by proper http server if possible. The built-in server is
   - blob view
   - commit patch view
 - JSON files:
-  - `flatgit.json`
+  - `manifest.json`
   - `refs.json`
   - `commits.json`
   - `tree.json`
@@ -145,10 +145,7 @@ The HMAC is SHA-256 over the raw request body.
 
 ## TODO
 
-- Add README rendering
 - Add syntax highlighting, probably with a tiny vendored/highlight-free first pass
 - Improve branch/tag URL escaping
-- Render per-branch trees instead of only the default branch
-- Add archive links
 - Add repo index page at the web-root
 - Add tests using temporary local Git repos
diff --git a/internal/buildinfo/buildinfo_gen.go b/internal/buildinfo/buildinfo_gen.go
index e1638c8..c7fcd79 100644
--- a/internal/buildinfo/buildinfo_gen.go
+++ b/internal/buildinfo/buildinfo_gen.go
@@ -2,6 +2,6 @@ package buildinfo
 
 const (
     Version     = "dev"
-    GitRevision = "c152a522ff4215c0dcc176118c4997f7f79fe770"
-    Timestamp   = "20260628.023834"
+    GitRevision = "b4e8406c82460f7b26dbf885ff5c6bf9a0b532f5"
+    Timestamp   = "20260704.125746"
 )
diff --git a/internal/render/archive.go b/internal/render/archive.go
new file mode 100644
index 0000000..9b8e8d6
--- /dev/null
+++ b/internal/render/archive.go
@@ -0,0 +1,48 @@
+package render
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"path/filepath"
+
+	"github.com/tgckpg/flatgit/internal/config"
+)
+
+func (r *Renderer) renderArchive(
+	ctx context.Context,
+	repo config.Repo,
+	next string,
+	commit string,
+	refSlug string,
+) error {
+	absNext, err := filepath.Abs(next)
+	if err != nil {
+		return fmt.Errorf("abs next path %s: %w", next, err)
+	}
+
+	archiveDir := filepath.Join(absNext, "archive")
+	outPath := filepath.Join(archiveDir, refSlug+".zip")
+
+	if err := os.MkdirAll(archiveDir, 0o755); err != nil {
+		return fmt.Errorf("mkdir archive dir %s: %w", archiveDir, err)
+	}
+
+	prefix := repo.Name + "-" + refSlug + "/"
+
+	_, err = r.Git.Output(
+		ctx,
+		repo.MirrorDir,
+		"archive",
+		"--format=zip",
+		"--prefix="+prefix,
+		"-o",
+		outPath,
+		commit,
+	)
+	if err != nil {
+		return fmt.Errorf("write archive %s for %s at %s: %w", outPath, repo.FullName(), commit, err)
+	}
+
+	return nil
+}
diff --git a/internal/render/manifest.go b/internal/render/manifest.go
index 3bf224e..bb81be1 100644
--- a/internal/render/manifest.go
+++ b/internal/render/manifest.go
@@ -106,7 +106,7 @@ func NewManifest(repo config.Repo, defaultBranch string, defaultCommit string) M
 			BlobMetadata: false,
 			RawBlobs:     true,
 			Search:       false,
-			Archive:      false,
+			Archive:      true,
 		},
 		GeneratedAt: time.Now(),
 	}
diff --git a/internal/render/render.go b/internal/render/render.go
index 6b70cac..dfc95ad 100644
--- a/internal/render/render.go
+++ b/internal/render/render.go
@@ -152,6 +152,10 @@ func (r *Renderer) RenderRepo(ctx context.Context, repo config.Repo) error {
 		return err
 	}
 
+	if err := r.renderArchive(ctx, repo, next, commit, branchSlug); err != nil {
+		return err
+	}
+
 	for _, c := range commits {
 		show, err := r.Git.Text(
 			ctx,
diff --git a/internal/render/templates.go b/internal/render/templates.go
index e86b876..3685a51 100644
--- a/internal/render/templates.go
+++ b/internal/render/templates.go
@@ -23,6 +23,7 @@ const layoutTemplate = `{{define "layout"}}<!doctype html>
 <a href="{{.RepoManifest.Repository.SitePath}}refs.html">refs</a>
 <a href="{{.RepoManifest.Repository.SitePath}}tree/{{.Ref}}/index.html">files</a>
 <a href="{{.RepoManifest.Repository.SitePath}}manifest.json" title="express view for bots and agents">json</a>
+<a href="{{.RepoManifest.Repository.SitePath}}archive/{{.RepoManifest.Repository.DefaultRefSlug}}.zip">zip ({{.RepoManifest.Repository.DefaultRefSlug}})</a>
 </nav>
 </header>
 <main>