aboutsummaryrefslogtreecommitdiff
path: root/format
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-08 14:15:55 +0800
committerGravatar Runxi Yu2026-03-08 14:15:55 +0800
commit4a17412255e294e99f2d11e9b8458e30bbe58292 (patch)
tree7d4b83d37abad439c61a5d626cf1609c0b3727d6 /format
parentinternal/progress: Add progress meter (diff)
signatureNo signature
format/pack/ingest: Use progress API
Diffstat (limited to 'format')
-rw-r--r--format/pack/ingest/api.go4
-rw-r--r--format/pack/ingest/ingest.go10
-rw-r--r--format/pack/ingest/progress_step.go9
-rw-r--r--format/pack/ingest/progress_write.go10
-rw-r--r--format/pack/ingest/resolve_all.go18
-rw-r--r--format/pack/ingest/scan.go22
-rw-r--r--format/pack/ingest/thin_fix.go21
7 files changed, 51 insertions, 43 deletions
diff --git a/format/pack/ingest/api.go b/format/pack/ingest/api.go
index 227f6a23..5df09213 100644
--- a/format/pack/ingest/api.go
+++ b/format/pack/ingest/api.go
@@ -23,6 +23,10 @@ type Options struct {
//
// When nil, no progress output is emitted.
Progress io.Writer
+ // ProgressFlush flushes transport output after progress writes.
+ //
+ // When nil, no explicit flush is attempted.
+ ProgressFlush func() error
// RequireTrailingEOF requires the source to hit EOF after the pack trailer.
//
// This is suitable for exact pack-file readers, but should be disabled for
diff --git a/format/pack/ingest/ingest.go b/format/pack/ingest/ingest.go
index e593510b..493942a0 100644
--- a/format/pack/ingest/ingest.go
+++ b/format/pack/ingest/ingest.go
@@ -2,8 +2,6 @@ package ingest
import (
"fmt"
-
- "codeberg.org/lindenii/furgit/internal/utils"
)
// ingest initializes transaction state and executes the ingest pipeline.
@@ -51,7 +49,7 @@ func ingest(state *ingestState) (out Result, err error) {
return Result{}, err
}
- utils.BestEffortFprintf(state.opts.Progress, "writing index...\r")
+ writeProgress(state, "writing index...\r")
err = state.packFile.Sync()
if err != nil {
@@ -63,10 +61,10 @@ func ingest(state *ingestState) (out Result, err error) {
return Result{}, err
}
- utils.BestEffortFprintf(state.opts.Progress, "writing index: done.\n")
+ writeProgress(state, "writing index: done.\n")
if state.opts.WriteRev {
- utils.BestEffortFprintf(state.opts.Progress, "writing reverse index...\r")
+ writeProgress(state, "writing reverse index...\r")
}
err = writeRev(state)
@@ -75,7 +73,7 @@ func ingest(state *ingestState) (out Result, err error) {
}
if state.opts.WriteRev {
- utils.BestEffortFprintf(state.opts.Progress, "writing reverse index: done.\n")
+ writeProgress(state, "writing reverse index: done.\n")
}
return finalizeArtifacts(state)
diff --git a/format/pack/ingest/progress_step.go b/format/pack/ingest/progress_step.go
deleted file mode 100644
index cdfc2322..00000000
--- a/format/pack/ingest/progress_step.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package ingest
-
-func progressStep(total uint32) uint32 {
- if total <= 200 {
- return 1
- }
-
- return total / 200
-}
diff --git a/format/pack/ingest/progress_write.go b/format/pack/ingest/progress_write.go
new file mode 100644
index 00000000..3150032b
--- /dev/null
+++ b/format/pack/ingest/progress_write.go
@@ -0,0 +1,10 @@
+package ingest
+
+import "codeberg.org/lindenii/furgit/internal/utils"
+
+func writeProgress(state *ingestState, format string, args ...any) {
+ utils.BestEffortFprintf(state.opts.Progress, format, args...)
+ if state.opts.ProgressFlush != nil {
+ _ = state.opts.ProgressFlush()
+ }
+}
diff --git a/format/pack/ingest/resolve_all.go b/format/pack/ingest/resolve_all.go
index 65cfe44b..e0ad2281 100644
--- a/format/pack/ingest/resolve_all.go
+++ b/format/pack/ingest/resolve_all.go
@@ -3,7 +3,7 @@ package ingest
import (
"errors"
- "codeberg.org/lindenii/furgit/internal/utils"
+ "codeberg.org/lindenii/furgit/internal/progress"
)
// resolveAll resolves all delta records and finalizes ObjectID/RealType for every record.
@@ -22,11 +22,14 @@ func resolveAll(state *ingestState) error {
return nil
}
- step := progressStep(pending)
-
var done uint32
- utils.BestEffortFprintf(state.opts.Progress, "resolving deltas: 0%% (0/%d)\r", pending)
+ meter := progress.New(progress.Options{
+ Writer: state.opts.Progress,
+ Flush: state.opts.ProgressFlush,
+ Title: "resolving deltas",
+ Total: uint64(pending),
+ })
for idx := range state.records {
if state.records[idx].resolved {
@@ -34,10 +37,7 @@ func resolveAll(state *ingestState) error {
}
done++
- if done%step == 0 || done == pending {
- percent := done * 100 / pending
- utils.BestEffortFprintf(state.opts.Progress, "resolving deltas: %3d%% (%d/%d)\r", percent, done, pending)
- }
+ meter.Set(uint64(done), 0)
visiting := make(map[int]struct{})
@@ -65,7 +65,7 @@ func resolveAll(state *ingestState) error {
state.baseCache.add(idx, ty, content)
}
- utils.BestEffortFprintf(state.opts.Progress, "resolving deltas: 100%% (%d/%d), done.\n", pending, pending)
+ meter.Stop("done")
return nil
}
diff --git a/format/pack/ingest/scan.go b/format/pack/ingest/scan.go
index bb94ebc3..8fe08ac3 100644
--- a/format/pack/ingest/scan.go
+++ b/format/pack/ingest/scan.go
@@ -3,7 +3,7 @@ package ingest
import (
"fmt"
- "codeberg.org/lindenii/furgit/internal/utils"
+ "codeberg.org/lindenii/furgit/internal/progress"
"codeberg.org/lindenii/furgit/objectid"
)
@@ -21,22 +21,27 @@ func streamPackAndScan(state *ingestState) error {
state.algo.Size(),
)
- utils.BestEffortFprintf(state.opts.Progress, "validating pack header...\r")
+ writeProgress(state, "validating pack header...\r")
err = seedStreamWithPackHeader(state)
if err != nil {
return err
}
- utils.BestEffortFprintf(state.opts.Progress, "validating pack header: done.\n")
+ writeProgress(state, "validating pack header: done.\n")
state.records = make([]objectRecord, 0, state.objectCountHeader)
state.ofsDeltas = make([]ofsDeltaRef, 0, state.objectCountHeader)
state.refDeltas = make([]refDeltaRef, 0, state.objectCountHeader)
total := state.objectCountHeader
- step := progressStep(total)
- utils.BestEffortFprintf(state.opts.Progress, "receiving objects: 0%% (0/%d)\r", total)
+ meter := progress.New(progress.Options{
+ Writer: state.opts.Progress,
+ Flush: state.opts.ProgressFlush,
+ Title: "receiving objects",
+ Total: uint64(total),
+ Throughput: true,
+ })
for i := range total {
nextOffset, err := scanOneEntry(state, state.stream.consumed)
@@ -49,13 +54,10 @@ func streamPackAndScan(state *ingestState) error {
}
done := i + 1
- if done%step == 0 || done == total {
- percent := done * 100 / total
- utils.BestEffortFprintf(state.opts.Progress, "receiving objects: %3d%% (%d/%d)\r", percent, done, total)
- }
+ meter.Set(uint64(done), state.stream.consumed)
}
- utils.BestEffortFprintf(state.opts.Progress, "receiving objects: 100%% (%d/%d), done.\n", total, total)
+ meter.Stop("done")
err = state.stream.finishAndFlushTrailer(state.opts.RequireTrailingEOF)
if err != nil {
diff --git a/format/pack/ingest/thin_fix.go b/format/pack/ingest/thin_fix.go
index 634f0367..22c237d2 100644
--- a/format/pack/ingest/thin_fix.go
+++ b/format/pack/ingest/thin_fix.go
@@ -4,7 +4,7 @@ import (
"fmt"
"codeberg.org/lindenii/furgit/internal/intconv"
- "codeberg.org/lindenii/furgit/internal/utils"
+ "codeberg.org/lindenii/furgit/internal/progress"
)
// maybeFixThin appends missing bases and rewrites pack header/trailer when needed.
@@ -13,8 +13,8 @@ func maybeFixThin(state *ingestState) error {
return nil
}
- utils.BestEffortFprintf(
- state.opts.Progress,
+ writeProgress(
+ state,
"fixing thin pack: %d unresolved bases\r",
len(state.unresolvedRefDeltas),
)
@@ -56,9 +56,13 @@ func maybeFixThin(state *ingestState) error {
baseIDs := unresolvedThinBaseIDs(state)
total := len(baseIDs)
- if total > 0 {
- utils.BestEffortFprintf(state.opts.Progress, "fixing thin pack: 0%% (0/%d)\r", total)
- }
+ meter := progress.New(progress.Options{
+ Writer: state.opts.Progress,
+ Flush: state.opts.ProgressFlush,
+ Title: "fixing thin pack",
+ Total: uint64(total),
+ Sparse: true,
+ })
for i, id := range baseIDs {
ty, content, err := state.opts.Base.ReadBytesContent(id)
@@ -74,8 +78,7 @@ func maybeFixThin(state *ingestState) error {
state.thinFixed = true
done := i + 1
- percent := done * 100 / total
- utils.BestEffortFprintf(state.opts.Progress, "fixing thin pack: %3d%% (%d/%d)\r", percent, done, total)
+ meter.Set(uint64(done), 0)
}
err = rewritePackHeaderAndTrailer(state)
@@ -84,7 +87,7 @@ func maybeFixThin(state *ingestState) error {
}
if state.thinFixed {
- utils.BestEffortFprintf(state.opts.Progress, "fixing thin pack: 100%% (%d/%d), done.\n", total, total)
+ meter.Stop("done")
}
return nil