diff --git a/core/commands/add.go b/core/commands/add.go index 1cd063120ce..3d6725822ba 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -13,7 +13,7 @@ import ( "github.com/ipfs/kubo/core/commands/cmdenv" "github.com/ipfs/kubo/core/commands/cmdutils" - "github.com/cheggaaa/pb" + "github.com/cheggaaa/pb/v3" "github.com/ipfs/boxo/files" uio "github.com/ipfs/boxo/ipld/unixfs/io" mfs "github.com/ipfs/boxo/mfs" @@ -76,6 +76,11 @@ const ( const ( adderOutChanSize = 8 + + // pb/v3 template used before the upload total is known: only the + // running byte counter and current speed. Swapped for + // cmdenv.ProgressBarFullTemplate once size discovery reports. + progressBarInitTemplate = `{{counters . }} {{speed . "%s/s" "?/s"}}` ) var AddCmd = &cmds.Command{ @@ -252,7 +257,7 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#import cmds.BoolOption(quietOptionName, "q", "Write minimal output."), cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."), cmds.BoolOption(silentOptionName, "Write no output."), - cmds.BoolOption(progressOptionName, "p", "Stream progress data."), + cmds.BoolOption(progressOptionName, "p", "Stream progress data. Defaults to true when stderr is a terminal."), // Basic Add Behavior cmds.BoolOption(onlyHashOptionName, "n", "Only chunk and hash - do not write to disk."), cmds.BoolOption(wrapOptionName, "w", "Wrap files with a directory object."), @@ -292,10 +297,10 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#import silent, _ := req.Options[silentOptionName].(bool) if !quiet && !silent { - // ipfs cli progress bar defaults to true unless quiet or silent is used + // default to showing progress only when stderr is a terminal _, found := req.Options[progressOptionName].(bool) if !found { - req.Options[progressOptionName] = true + req.Options[progressOptionName] = cmdenv.IsTerminal(os.Stderr) } } @@ -732,11 +737,8 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#import var bar *pb.ProgressBar if progress { - bar = pb.New64(0).SetUnits(pb.U_BYTES) - bar.ManualUpdate = true - bar.ShowTimeLeft = false - bar.ShowPercent = false - bar.Output = os.Stderr + bar = pb.New64(0).Set(pb.Bytes, true).Set(pb.Static, true).SetWriter(os.Stderr) + bar.SetTemplateString(progressBarInitTemplate) bar.Start() } @@ -786,18 +788,17 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#import } lastBytes = output.Bytes delta := prevFiles + lastBytes - totalProgress - totalProgress = bar.Add64(delta) + bar.Add64(delta) + totalProgress = bar.Current() } if progress { - bar.Update() + bar.Write() } case size := <-sizeChan: if progress { - bar.Total = size - bar.ShowPercent = true - bar.ShowBar = true - bar.ShowTimeLeft = true + bar.SetTotal(size) + bar.SetTemplateString(cmdenv.ProgressBarFullTemplate) } case <-req.Context.Done(): // don't set or print error here, that happens in the goroutine below @@ -805,12 +806,19 @@ https://github.com/ipfs/kubo/blob/master/docs/config.md#import } } - if progress && bar.Total == 0 && bar.Get() != 0 { - bar.Total = bar.Get() - bar.ShowPercent = true - bar.ShowBar = true - bar.ShowTimeLeft = true - bar.Update() + if progress { + // If size discovery never reported, treat the + // observed bytes as the total so the final frame + // renders the bar and percent. + if bar.Total() == 0 && bar.Current() != 0 { + bar.SetTotal(bar.Current()) + bar.SetTemplateString(cmdenv.ProgressBarFullTemplate) + } + // Finish first so the speed element switches to + // the absolute-rate branch (total/elapsed) when + // EWMA never accumulated a sample on fast adds. + bar.Finish() + bar.Write() } } diff --git a/core/commands/cat.go b/core/commands/cat.go index 140a62cd344..97a7a3f556f 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -10,7 +10,7 @@ import ( "github.com/ipfs/kubo/core/commands/cmdenv" "github.com/ipfs/kubo/core/commands/cmdutils" - "github.com/cheggaaa/pb" + "github.com/cheggaaa/pb/v3" "github.com/ipfs/boxo/files" cmds "github.com/ipfs/go-ipfs-cmds" iface "github.com/ipfs/kubo/core/coreiface" @@ -34,7 +34,7 @@ var CatCmd = &cmds.Command{ Options: []cmds.Option{ cmds.Int64Option(offsetOptionName, "o", "Byte offset to begin reading from."), cmds.Int64Option(lengthOptionName, "l", "Maximum number of bytes to read."), - cmds.BoolOption(progressOptionName, "p", "Stream progress data.").WithDefault(true), + cmds.BoolOption(progressOptionName, "p", "Stream progress data. Defaults to true when stderr is a terminal."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env, req) @@ -101,9 +101,7 @@ var CatCmd = &cmds.Command{ case io.Reader: reader := val - req := res.Request() - progress, _ := req.Options[progressOptionName].(bool) - if progress { + if cmdenv.ShouldShowProgress(res.Request(), progressOptionName) { var bar *pb.ProgressBar bar, reader = progressBarForReader(os.Stderr, val, int64(res.Length())) bar.Start() diff --git a/core/commands/cmdenv/progress.go b/core/commands/cmdenv/progress.go new file mode 100644 index 00000000000..a4b32d4b4c9 --- /dev/null +++ b/core/commands/cmdenv/progress.go @@ -0,0 +1,24 @@ +package cmdenv + +import ( + "os" + + cmds "github.com/ipfs/go-ipfs-cmds" +) + +// ProgressBarFullTemplate is the pb/v3 template used by transfer +// commands once the total byte count is known: byte counter, bar, +// speed, percent, and ETA. Explicit format args override pb's +// defaults so the rate renders as "MiB/s" (not "MiB p/s") and the +// remaining time falls back to "ETA ?" while speed is unknown. +const ProgressBarFullTemplate = `{{counters . }} {{bar . }} {{speed . "%s/s" "?/s"}} {{percent . }} {{rtime . "ETA %s" "%s" "ETA ?"}}` + +// ShouldShowProgress reports whether a progress bar should be rendered +// based on a boolean option. An explicit `--=true|false` always +// wins; when unset, it defaults to whether stderr is a terminal. +func ShouldShowProgress(req *cmds.Request, flag string) bool { + if v, ok := req.Options[flag].(bool); ok { + return v + } + return IsTerminal(os.Stderr) +} diff --git a/core/commands/cmdenv/progress_test.go b/core/commands/cmdenv/progress_test.go new file mode 100644 index 00000000000..c33409ad0c5 --- /dev/null +++ b/core/commands/cmdenv/progress_test.go @@ -0,0 +1,46 @@ +package cmdenv + +import ( + "os" + "testing" + + cmds "github.com/ipfs/go-ipfs-cmds" +) + +func TestShouldShowProgress(t *testing.T) { + const flag = "progress" + makeReq := func(opts map[string]any) *cmds.Request { + if opts == nil { + opts = map[string]any{} + } + return &cmds.Request{Options: opts} + } + + t.Run("explicit true wins regardless of TTY", func(t *testing.T) { + if !ShouldShowProgress(makeReq(map[string]any{flag: true}), flag) { + t.Error("expected true for --progress=true") + } + }) + + t.Run("explicit false wins regardless of TTY", func(t *testing.T) { + if ShouldShowProgress(makeReq(map[string]any{flag: false}), flag) { + t.Error("expected false for --progress=false") + } + }) + + t.Run("unset defaults to IsTerminal(stderr)", func(t *testing.T) { + got := ShouldShowProgress(makeReq(nil), flag) + want := IsTerminal(os.Stderr) + if got != want { + t.Errorf("ShouldShowProgress(unset) = %v, want IsTerminal(os.Stderr) = %v", got, want) + } + }) + + t.Run("non-bool value treated as unset", func(t *testing.T) { + got := ShouldShowProgress(makeReq(map[string]any{flag: "yes"}), flag) + want := IsTerminal(os.Stderr) + if got != want { + t.Errorf("ShouldShowProgress(non-bool) = %v, want IsTerminal(os.Stderr) = %v", got, want) + } + }) +} diff --git a/core/commands/cmdenv/tty.go b/core/commands/cmdenv/tty.go new file mode 100644 index 00000000000..5bf232dd0aa --- /dev/null +++ b/core/commands/cmdenv/tty.go @@ -0,0 +1,14 @@ +package cmdenv + +import ( + "os" + + "github.com/mattn/go-isatty" +) + +// IsTerminal reports whether f is connected to a terminal, +// including MSYS/Cygwin-style terminals on Windows. +func IsTerminal(f *os.File) bool { + fd := f.Fd() + return isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd) +} diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 0e737ec6c11..e4103581971 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -286,7 +286,7 @@ CAR file follows the CARv1 format: https://ipld.io/specs/transport/car/carv1/ cmds.StringArg("root", true, false, "CID of a root to recursively export").EnableStdin(), }, Options: []cmds.Option{ - cmds.BoolOption(progressOptionName, "p", "Display progress on CLI. Defaults to true when STDERR is a TTY."), + cmds.BoolOption(progressOptionName, "p", "Stream progress data. Defaults to true when stderr is a terminal."), }, Run: dagExport, PostRun: cmds.PostRunMap{ @@ -352,7 +352,7 @@ Note: This command skips duplicate blocks in reporting both size and the number cmds.StringArg("root", true, true, "CID of a DAG root to get statistics for").EnableStdin(), }, Options: []cmds.Option{ - cmds.BoolOption(progressOptionName, "p", "Show progress on stderr. Auto-detected if stderr is a terminal."), + cmds.BoolOption(progressOptionName, "p", "Stream progress data. Defaults to true when stderr is a terminal."), }, Run: dagStat, Type: DagStatSummary{}, diff --git a/core/commands/dag/export.go b/core/commands/dag/export.go index 48223f86083..3efad02f46b 100644 --- a/core/commands/dag/export.go +++ b/core/commands/dag/export.go @@ -8,7 +8,7 @@ import ( "os" "time" - "github.com/cheggaaa/pb" + "github.com/cheggaaa/pb/v3" cid "github.com/ipfs/go-cid" cmds "github.com/ipfs/go-ipfs-cmds" ipld "github.com/ipfs/go-ipld-format" @@ -20,6 +20,13 @@ import ( selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse" ) +// pb/v3 template for `ipfs dag export`: byte counter, speed, and +// elapsed time. No bar/percent/ETA because the total size of the +// CAR stream is not known up front. The explicit "%s/s" speed +// format overrides pb's default "p/s" suffix so the rate renders +// as "MiB/s". +const progressBarTemplate = `{{counters . }} {{speed . "%s/s" "?/s"}} {{etime . }}` + func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { // Accept CID or a content path p, err := cmdutils.PathOrCidPath(req.Arguments[0]) @@ -99,28 +106,12 @@ func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment } func finishCLIExport(res cmds.Response, re cmds.ResponseEmitter) error { - var showProgress bool - val, specified := res.Request().Options[progressOptionName] - if !specified { - // default based on TTY availability - errStat, _ := os.Stderr.Stat() - if (errStat.Mode() & os.ModeCharDevice) != 0 { - showProgress = true - } - } else if val.(bool) { - showProgress = true - } - - // simple passthrough, no progress - if !showProgress { + if !cmdenv.ShouldShowProgress(res.Request(), progressOptionName) { return cmds.Copy(re, res) } - bar := pb.New64(0).SetUnits(pb.U_BYTES) - bar.Output = os.Stderr - bar.ShowSpeed = true - bar.ShowElapsedTime = true - bar.RefreshRate = 500 * time.Millisecond + bar := pb.New64(0).Set(pb.Bytes, true).SetWriter(os.Stderr).SetRefreshRate(500 * time.Millisecond) + bar.SetTemplateString(progressBarTemplate) bar.Start() var processedOneResponse bool diff --git a/core/commands/dag/stat.go b/core/commands/dag/stat.go index 0ce1e4246f4..6602789bdb8 100644 --- a/core/commands/dag/stat.go +++ b/core/commands/dag/stat.go @@ -95,17 +95,7 @@ func dagStat(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) } func finishCLIStat(res cmds.Response, re cmds.ResponseEmitter) error { - // Determine whether to show progress based on TTY detection or explicit flag - var showProgress bool - val, specified := res.Request().Options[progressOptionName] - if !specified { - // Auto-detect: show progress only if stderr is a TTY - if errStat, err := os.Stderr.Stat(); err == nil { - showProgress = (errStat.Mode() & os.ModeCharDevice) != 0 - } - } else { - showProgress = val.(bool) - } + showProgress := cmdenv.ShouldShowProgress(res.Request(), progressOptionName) var dagStats *DagStatSummary for { diff --git a/core/commands/get.go b/core/commands/get.go index 804836b9afd..f5c7160331d 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -16,7 +16,7 @@ import ( "github.com/ipfs/kubo/core/commands/cmdutils" "github.com/ipfs/kubo/core/commands/e" - "github.com/cheggaaa/pb" + "github.com/cheggaaa/pb/v3" "github.com/ipfs/boxo/files" "github.com/ipfs/boxo/tar" cmds "github.com/ipfs/go-ipfs-cmds" @@ -58,7 +58,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. cmds.BoolOption(archiveOptionName, "a", "Output a TAR archive."), cmds.BoolOption(compressOptionName, "C", "Compress the output with GZIP compression."), cmds.IntOption(compressionLevelOptionName, "l", "The level of compression (1-9)."), - cmds.BoolOption(progressOptionName, "p", "Stream progress data.").WithDefault(true), + cmds.BoolOption(progressOptionName, "p", "Stream progress data. Defaults to true when stderr is a terminal."), }, PreRun: func(req *cmds.Request, env cmds.Environment) error { _, err := getCompressOptions(req) @@ -140,7 +140,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. } archive, _ := req.Options[archiveOptionName].(bool) - progress, _ := req.Options[progressOptionName].(bool) + showProgress := cmdenv.ShouldShowProgress(req, progressOptionName) gw := getWriter{ Out: os.Stdout, @@ -148,7 +148,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. Archive: archive, Compression: cmplvl, Size: int64(res.Length()), - Progress: progress, + Progress: showProgress, } return gw.Write(outReader, outPath) @@ -177,19 +177,7 @@ func progressBarForReader(out io.Writer, r io.Reader, l int64) (*pb.ProgressBar, } func makeProgressBar(out io.Writer, l int64) *pb.ProgressBar { - // setup bar reader - // TODO: get total length of files - bar := pb.New64(l).SetUnits(pb.U_BYTES) - bar.Output = out - - // the progress bar lib doesn't give us a way to get the width of the output, - // so as a hack we just use a callback to measure the output, then get rid of it - bar.Callback = func(line string) { - terminalWidth := len(line) - bar.Callback = nil - log.Infof("terminal width: %v\n", terminalWidth) - } - return bar + return pb.New64(l).Set(pb.Bytes, true).SetTemplateString(cmdenv.ProgressBarFullTemplate).SetWriter(out) } func getOutPath(req *cmds.Request) string { @@ -260,8 +248,8 @@ func (gw *getWriter) writeExtracted(r io.Reader, fpath string) error { bar := makeProgressBar(gw.Err, gw.Size) bar.Start() defer bar.Finish() - defer bar.Set64(gw.Size) - progressCb = bar.Add64 + defer bar.SetCurrent(gw.Size) + progressCb = func(n int64) int64 { bar.Add64(n); return bar.Current() } } extractor := &tar.Extractor{Path: fpath, Progress: progressCb} diff --git a/docs/changelogs/v0.42.md b/docs/changelogs/v0.42.md index 7c431d5752c..52117c293a7 100644 --- a/docs/changelogs/v0.42.md +++ b/docs/changelogs/v0.42.md @@ -17,6 +17,7 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team. - [๐Ÿ› Reliable shutdown and container health checks](#-reliable-shutdown-and-container-health-checks) - [๐Ÿšจ ERROR log for listeners blocked by `Swarm.AddrFilters` or `Addresses.NoAnnounce`](#-error-log-for-listeners-blocked-by-swarmaddrfilters-or-addressesnoannounce) - [๐Ÿ“Š OpenTelemetry: scope info now exposed as labels](#-opentelemetry-scope-info-now-exposed-as-labels) + - [๐Ÿ”ง Cleaner progress bars](#-cleaner-progress-bars) - [๐Ÿ“ฆ๏ธ Dependency updates](#-dependency-updates) - [๐Ÿ“ Changelog](#-changelog) - [๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Contributors](#-contributors) @@ -89,11 +90,18 @@ Kubo now logs an ERROR when an [`Addresses.Swarm`](https://github.com/ipfs/kubo/ The Prometheus endpoint no longer emits the `otel_scope_info` metric. Each metric now carries `otel_scope_name`, `otel_scope_version`, and `otel_scope_schema_url` labels identifying the instrumentation library that produced it. Update dashboards or queries that read `otel_scope_info` to consume these labels instead. See [`docs/metrics.md`](https://github.com/ipfs/kubo/blob/master/docs/metrics.md) for details. +#### ๐Ÿ”ง Cleaner progress bars + +`ipfs add`, `ipfs cat`, and `ipfs get` now hide their progress bar when stderr is piped or redirected, so a command like `ipfs add file 2> log.txt` no longer fills the log with progress-bar noise. Pass `--progress=true` to force the bar on, or `--progress=false` to hide it. + +`ipfs dag export` and `ipfs dag stat` now correctly recognize MSYS2 and Git Bash terminals on Windows. Previously the bar was suppressed there even when running interactively. + #### ๐Ÿ“ฆ๏ธ Dependency updates - update `go-libp2p-pubsub` to [v0.16.0](https://github.com/libp2p/go-libp2p-pubsub/releases/tag/v0.16.0) - update `go-libp2p-kad-dht` to [b73e1e8](https://github.com/libp2p/go-libp2p-kad-dht/commit/b73e1e814f5f82e3554d350e61e33cae551084f6) (post-v0.39.2, includes [#1251](https://github.com/libp2p/go-libp2p-kad-dht/pull/1251) and [#1252](https://github.com/libp2p/go-libp2p-kad-dht/pull/1252)) - update `go-fuse/v2` to [v2.10.1](https://github.com/hanwen/go-fuse/releases/tag/v2.10.1) +- update `cheggaaa/pb` to [v3.1.7](https://github.com/cheggaaa/pb/releases/tag/v3.1.7) ### ๐Ÿ“ Changelog diff --git a/go.mod b/go.mod index 4b260cadc17..c6cd59748a4 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/caddyserver/certmagic v0.23.0 github.com/cenkalti/backoff/v4 v4.3.0 github.com/ceramicnetwork/go-dag-jose v0.1.1 - github.com/cheggaaa/pb v1.0.29 + github.com/cheggaaa/pb/v3 v3.1.7 github.com/cockroachdb/pebble/v2 v2.1.5 github.com/coreos/go-systemd/v22 v22.7.0 github.com/dustin/go-humanize v1.0.1 @@ -60,6 +60,7 @@ require ( github.com/libp2p/go-libp2p-routing-helpers v0.7.5 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-socket-activation v0.1.1 + github.com/mattn/go-isatty v0.0.22 github.com/miekg/dns v1.1.72 github.com/multiformats/go-multiaddr v0.16.1 github.com/multiformats/go-multiaddr-dns v0.5.0 @@ -104,6 +105,7 @@ require ( github.com/Jorropo/jsync v1.0.1 // indirect github.com/RaduBerinde/axisds v0.1.0 // indirect github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 // indirect + github.com/VividCortex/ewma v1.2.0 // indirect github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -127,7 +129,7 @@ require ( github.com/dgraph-io/ristretto v0.0.2 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dunglas/httpsfv v1.1.0 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/filecoin-project/go-clock v0.1.0 // indirect github.com/flynn/noise v1.1.0 // indirect @@ -179,9 +181,8 @@ require ( github.com/libp2p/go-yamux/v5 v5.0.1 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.22 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mholt/acmez/v3 v3.1.2 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect @@ -225,7 +226,7 @@ require ( github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect github.com/quic-go/webtransport-go v0.10.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/slok/go-http-metrics v0.13.0 // indirect diff --git a/go.sum b/go.sum index b4d0b0dae9e..e6e2bb56055 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,8 @@ github.com/RaduBerinde/axisds v0.1.0 h1:YItk/RmU5nvlsv/awo2Fjx97Mfpt4JfgtEVAGPrL github.com/RaduBerinde/axisds v0.1.0/go.mod h1:UHGJonU9z4YYGKJxSaC6/TNcLOBptpmM5m2Cksbnw0Y= github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 h1:bsU8Tzxr/PNz75ayvCnxKZWEYdLMPDkUgticP4a4Bvk= github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54/go.mod h1:0tr7FllbE9gJkHq7CVeeDDFAFKQVy5RnCSSNBOvdqbc= +github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= +github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f h1:JjxwchlOepwsUWcQwD2mLUAGE9aCp0/ehy6yCHFBOvo= github.com/aclements/go-perfevent v0.0.0-20240301234650-f7843625020f/go.mod h1:tMDTce/yLLN/SK8gMOxQfnyeMeCg8KGzp0D1cbECEeo= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -116,8 +118,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= -github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI= +github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -194,9 +196,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU= @@ -591,20 +592,15 @@ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -815,8 +811,8 @@ github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRC github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1230,7 +1226,6 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=