ref: 9e44418ce9d88f4159067b1ce2c808cb93e29c38
dir: /cmd/index-pack/main.go/
// Command index-pack ingests one pack stream from stdin and writes .pack/.idx/.rev.
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"codeberg.org/lindenii/furgit/format/pack/ingest"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objectstore"
"codeberg.org/lindenii/furgit/repository"
)
func main() {
repoPath := flag.String("r", "", "path to git dir (.git or bare repo root)")
destinationPath := flag.String("destination", "", "path to destination objects/pack directory")
objectFormat := flag.String("object-format", "", "object format (sha1 or sha256)")
fixThin := flag.Bool("fix-thin", false, "fix thin packs using repository object store")
writeRev := flag.Bool("rev-index", true, "write reverse index (.rev)")
flag.Parse()
if *destinationPath == "" {
log.Fatal("must provide -destination <objects/pack>")
}
err := run(*repoPath, *destinationPath, *objectFormat, *fixThin, *writeRev)
if err != nil {
log.Fatalf("run: %v", err)
}
}
func run(repoPath, destinationPath, objectFormat string, fixThin, writeRev bool) error {
var (
algo objectid.Algorithm
base objectstore.Store
repo *repository.Repository
)
if repoPath != "" {
repoRoot, err := os.OpenRoot(repoPath)
if err != nil {
return fmt.Errorf("open repo root: %w", err)
}
defer func() { _ = repoRoot.Close() }()
repo, err = repository.Open(repoRoot)
if err != nil {
return fmt.Errorf("open repository: %w", err)
}
defer func() { _ = repo.Close() }()
}
algo, err := resolveAlgorithm(repo, objectFormat)
if err != nil {
return err
}
if fixThin {
if repo == nil {
return fmt.Errorf("fix-thin requires -r <repo>")
}
if repo.Algorithm() != algo {
return fmt.Errorf("algorithm mismatch: repo=%s flag=%s", repo.Algorithm(), algo)
}
base = repo.Objects()
}
absDestination, err := filepath.Abs(destinationPath)
if err != nil {
return fmt.Errorf("absolute destination path: %w", err)
}
destinationRoot, err := os.OpenRoot(absDestination)
if err != nil {
return fmt.Errorf("open destination root: %w", err)
}
defer func() { _ = destinationRoot.Close() }()
result, err := ingest.Ingest(os.Stdin, destinationRoot, algo, fixThin, writeRev, base)
if err != nil {
return err
}
_, _ = fmt.Fprintf(os.Stdout, "pack\t%s\n", result.PackHash.String())
return nil
}
func resolveAlgorithm(repo *repository.Repository, objectFormat string) (objectid.Algorithm, error) {
if objectFormat != "" {
algo, ok := objectid.ParseAlgorithm(objectFormat)
if !ok {
return objectid.AlgorithmUnknown, fmt.Errorf("invalid object format %q", objectFormat)
}
return algo, nil
}
if repo != nil {
return repo.Algorithm(), nil
}
return objectid.AlgorithmSHA1, nil
}