main
Raw Download raw file
  1package cli
  2
  3import (
  4	"flag"
  5	"fmt"
  6	"log/slog"
  7	"os"
  8	"path/filepath"
  9
 10	"forge/internal/gitmal"
 11	"forge/internal/index"
 12	"forge/internal/repo"
 13)
 14
 15func runStatic(args []string) error {
 16	fs := flag.NewFlagSet("forge static", flag.ContinueOnError)
 17	fs.SetOutput(os.Stderr)
 18
 19	root := fs.String("root", "/opt/git", "path to bare repo root")
 20	output := fs.String("output", "/var/www/git", "path to output directory")
 21	all := fs.Bool("all", false, "discover and process all repos")
 22
 23	err := fs.Parse(args)
 24	if err != nil {
 25		return err
 26	}
 27
 28	positional := fs.Args()
 29
 30	if *all && len(positional) > 0 {
 31		fmt.Fprintln(os.Stderr, "error: --all cannot be combined with positional arguments")
 32		return ErrUsage
 33	}
 34
 35	if !*all && len(positional) == 0 {
 36		fmt.Fprintln(os.Stderr, "error: provide a repo path or use --all")
 37		fs.Usage()
 38		return ErrUsage
 39	}
 40
 41	if *all {
 42		return staticAll(*root, *output)
 43	}
 44
 45	return staticOne(*root, *output, positional[0])
 46}
 47
 48func staticAll(root, output string) error {
 49	repos, err := repo.Discover(root)
 50	if err != nil {
 51		return err
 52	}
 53
 54	slog.Info("discovered repos", slog.Int("count", len(repos)))
 55
 56	var failed int
 57	for _, r := range repos {
 58		slog.Info("processing", slog.String("repo", r.RelPath))
 59		outDir := filepath.Join(output, r.RelPath)
 60		err := gitmal.Run(r.FullPath, r.Name, outDir)
 61		if err != nil {
 62			slog.Warn("skipping repo",
 63				slog.String("repo", r.RelPath),
 64				slog.String("error", err.Error()))
 65			failed++
 66		}
 67	}
 68
 69	err = index.GenerateAll(output, repos)
 70	if err != nil {
 71		return err
 72	}
 73
 74	slog.Info("indexes generated")
 75
 76	if failed > 0 {
 77		return fmt.Errorf("gitmal failed for %d repo(s)", failed)
 78	}
 79	return nil
 80}
 81
 82func staticOne(root, output, relPath string) error {
 83	if filepath.IsAbs(relPath) {
 84		fmt.Fprintln(os.Stderr, "error: repo path must be relative")
 85		return ErrUsage
 86	}
 87
 88	fullPath := filepath.Join(root, relPath)
 89
 90	bare, err := repo.IsBare(fullPath)
 91	if err != nil {
 92		return err
 93	}
 94	if !bare {
 95		return fmt.Errorf("not a bare repo (path=%s): %w", fullPath, ErrUsage)
 96	}
 97
 98	name := filepath.Base(relPath)
 99	outDir := filepath.Join(output, relPath)
100
101	slog.Info("processing",
102		slog.String("repo", relPath),
103		slog.String("output", outDir))
104
105	err = gitmal.Run(fullPath, name, outDir)
106	if err != nil {
107		return err
108	}
109
110	return nil
111}