Artifact 2ecae7a413966eac8a9785161b35bce51e90db365d75d6d29961e3f820a50eb9:
- File
cli/repo_extract.go
— part of check-in
[f5744359d3]
at
2026-04-19 16:30:54
on branch trunk
— Initial open source release
libfossil is a pure-Go implementation of the Fossil SCM, reading and writing the same .fossil SQLite repository format as upstream Fossil.
This is the first public release of code that previously lived in a private repository. The module path is github.com/danmestas/libfossil and the binary is named libfossil to avoid $PATH collisions with upstream fossil.
Included: - Repo lifecycle (create, clone), checkout/checkin, timeline, merge, diff, annotate, shun, tag, branch, bisect, stash, undo/redo - Sync-over-HTTP protocol (client and handler) - Two SQLite drivers: modernc (pure Go, default) and ncruces (wasm-capable) - Observer interfaces (SyncObserver, CheckoutObserver) with an optional OpenTelemetry implementation in observer/otel (separate submodule) - Deterministic simulation testing harness with BUGGIFY fault injection - Kong-based embeddable CLI under cli/ and a standalone binary under cmd/libfossil/ (user: [email protected], size: 1870) [annotate] [blame] [check-ins using]
package cli import ( "fmt" "os" "path/filepath" "github.com/danmestas/libfossil/internal/blob" "github.com/danmestas/libfossil/internal/content" ) // RepoExtractCmd extracts files from a version. type RepoExtractCmd struct { Version string `help:"Version to extract from (default: tip)"` Files []string `arg:"" optional:"" help:"Files to extract (default: all)"` Dir string `short:"d" help:"Output directory" default:"."` } func (c *RepoExtractCmd) Run(g *Globals) error { r, err := g.OpenRepo() if err != nil { return err } defer r.Close() rid, err := resolveRID(r, c.Version) if err != nil { return err } allFiles, err := r.ListFiles(rid) if err != nil { return err } db := r.Inner().DB() // Filter to requested files if specified. type fileInfo struct { Name string UUID string Perm string } var files []fileInfo if len(c.Files) > 0 { wanted := make(map[string]bool) for _, f := range c.Files { wanted[f] = true } for _, f := range allFiles { if wanted[f.Name] { files = append(files, fileInfo{f.Name, f.UUID, f.Perm}) } } if len(files) == 0 { return fmt.Errorf("no matching files found") } } else { for _, f := range allFiles { files = append(files, fileInfo{f.Name, f.UUID, f.Perm}) } } for _, f := range files { fileRid, ok := blob.Exists(db, f.UUID) if !ok { return fmt.Errorf("blob %s not found for %s", f.UUID, f.Name) } data, err := content.Expand(db, fileRid) if err != nil { return fmt.Errorf("expanding %s: %w", f.Name, err) } outPath := filepath.Join(c.Dir, f.Name) if err := os.MkdirAll(filepath.Dir(outPath), 0o755); err != nil { return err } perm := os.FileMode(0o644) if f.Perm == "x" { perm = 0o755 } if err := os.WriteFile(outPath, data, perm); err != nil { return err } fmt.Println(f.Name) } return nil }