aboutsummaryrefslogtreecommitdiff
path: root/object/store/packed/internal/ingest/thin_fix.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-30 14:28:13 +0000
committerGravatar Runxi Yu2026-03-30 14:28:13 +0000
commita4eeb727468a178a4de0dfc718828f26740484ac (patch)
tree4318d38d49facc80e2e2186f5919fa656be3b31f /object/store/packed/internal/ingest/thin_fix.go
parentobject/store/packed: Make store own root, algo, opts (diff)
signatureNo signature
object,store/packed{,/internal/ingest}: Move from format/packfile/ingest
Diffstat (limited to 'object/store/packed/internal/ingest/thin_fix.go')
-rw-r--r--object/store/packed/internal/ingest/thin_fix.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/object/store/packed/internal/ingest/thin_fix.go b/object/store/packed/internal/ingest/thin_fix.go
new file mode 100644
index 00000000..f66ed279
--- /dev/null
+++ b/object/store/packed/internal/ingest/thin_fix.go
@@ -0,0 +1,99 @@
+package ingest
+
+import (
+ "errors"
+ "fmt"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
+ "codeberg.org/lindenii/furgit/internal/progress"
+ objectstore "codeberg.org/lindenii/furgit/object/store"
+)
+
+// maybeFixThin appends missing bases and rewrites pack header/trailer when needed.
+func maybeFixThin(state *ingestState) error {
+ if len(state.unresolvedRefDeltas) == 0 {
+ return nil
+ }
+
+ writeProgressf(
+ state,
+ "fixing thin pack: %d unresolved bases\r",
+ len(state.unresolvedRefDeltas),
+ )
+
+ if !state.opts.FixThin {
+ return &ThinPackUnresolvedError{Count: len(state.unresolvedRefDeltas)}
+ }
+
+ if state.opts.Base == nil {
+ return &ThinPackUnresolvedError{Count: len(state.unresolvedRefDeltas)}
+ }
+
+ hashSize := int64(state.algo.Size())
+
+ info, err := state.packFile.Stat()
+ if err != nil {
+ return err
+ }
+
+ size := info.Size()
+ if size < hashSize {
+ return fmt.Errorf("packfile/ingest: pack too short to trim trailer")
+ }
+
+ newEnd := size - hashSize
+
+ err = state.packFile.Truncate(newEnd)
+ if err != nil {
+ return err
+ }
+
+ consumed, err := intconv.Int64ToUint64(newEnd)
+ if err != nil {
+ return err
+ }
+
+ state.stream.consumed = consumed
+
+ baseIDs := unresolvedThinBaseIDs(state)
+
+ total := len(baseIDs)
+ meter := progress.New(progress.Options{
+ Writer: state.opts.Progress,
+ Title: "fixing thin pack",
+ Total: uint64(total),
+ })
+ meter.Set(0, 0)
+
+ var appended uint64
+
+ for _, id := range baseIDs {
+ ty, content, err := state.opts.Base.ReadBytesContent(id)
+ if err != nil {
+ if errors.Is(err, objectstore.ErrObjectNotFound) {
+ continue
+ }
+
+ return fmt.Errorf("packfile/ingest: read thin base %s: %w", id, err)
+ }
+
+ _, err = appendBaseObject(state, id, ty, content)
+ if err != nil {
+ return err
+ }
+
+ state.thinFixed = true
+
+ appended++
+ meter.Set(appended, 0)
+ }
+
+ err = rewritePackHeaderAndTrailer(state)
+ if err != nil {
+ return err
+ }
+
+ meter.Stop(fmt.Sprintf("appended %d/%d, done", appended, total))
+
+ return nil
+}