diff options
Diffstat (limited to 'cmd/index-pack')
| -rw-r--r-- | cmd/index-pack/main.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/cmd/index-pack/main.go b/cmd/index-pack/main.go new file mode 100644 index 00000000..12d01ed8 --- /dev/null +++ b/cmd/index-pack/main.go @@ -0,0 +1,107 @@ +// 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 +} |
