@cryptotaxi247 / kubo / commits / d37b92bfc

fix: `ipfs pin ls <cid> --names` (#10970)

* fix: use CheckIfPinnedWithType for pin ls with names updates to use CheckIfPinnedWithType method from https://github.com/ipfs/boxo/pull/1035, enabling efficient pin name retrieval for 'ipfs pin ls <cid> --names' - uses new CheckIfPinnedWithType from boxo for type-specific pin checks - pin names are now returned when listing specific CIDs with --names flag * test: add CLI tests for pin ls with names tests cover: - pin ls with specific CIDs returning names - pin ls without CID listing all pins with names - pin ls with --type and --names combinations - JSON output with and without names - pin update preserving names - error cases (invalid CID, unpinned CID) * docs: add pin name improvements to v0.38 changelog covers fix for ipfs pin ls --names with specific CIDs and RPC pin name leak fix * fix(rpc): support pin names in Add() passes the Name field from PinAddSettings to the API request adds test to verify pin names work via RPC * test: add coverage for pin names functionality - test special characters, unicode, long names - test concurrent operations - test persistence across daemon restarts - test garbage collection preservation - fix indirect pin test logic * chore: boxo@main with boxo#1039 * fix(pin): improve pin ls robustness and validation - add nil check for n.Pinning with early fail-fast validation - use pin.StringToMode() for consistent type validation - add edge case tests for invalid types and unpinned CIDs

Marcin Rataj committed Sep 19, 2025 at 03:17 UTC d37b92bfcd52d1b4ae8493f55111b9c47a33fa54
11 files changed +835 -141
client/rpc/pin.go
+6 -2
@@ -52,8 +52,12 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp
52 return err
53 }
54
55 - return api.core().Request("pin/add", p.String()).
56 - Option("recursive", options.Recursive).Exec(ctx, nil)
55 + req := api.core().Request("pin/add", p.String()).
56 + Option("recursive", options.Recursive)
57 + if options.Name != "" {
58 + req = req.Option("name", options.Name)
59 + }
60 + return req.Exec(ctx, nil)
61 }
62
63 type pinLsObject struct {
core/commands/pin/pin.go
+37 -34
@@ -11,6 +11,7 @@ import (
11 bserv "github.com/ipfs/boxo/blockservice"
12 offline "github.com/ipfs/boxo/exchange/offline"
13 dag "github.com/ipfs/boxo/ipld/merkledag"
14 + pin "github.com/ipfs/boxo/pinning/pinner"
15 verifcid "github.com/ipfs/boxo/verifcid"
16 cid "github.com/ipfs/go-cid"
17 cidenc "github.com/ipfs/go-cidutil/cidenc"
@@ -370,16 +371,23 @@ Example:
371 return err
372 }
373
374 + n, err := cmdenv.GetNode(env)
375 + if err != nil {
376 + return err
377 + }
378 +
379 + if n.Pinning == nil {
380 + return fmt.Errorf("pinning service not available")
381 + }
382 +
383 typeStr, _ := req.Options[pinTypeOptionName].(string)
384 stream, _ := req.Options[pinStreamOptionName].(bool)
385 displayNames, _ := req.Options[pinNamesOptionName].(bool)
386 name, _ := req.Options[pinNameOptionName].(string)
387
378 - switch typeStr {
379 - case "all", "direct", "indirect", "recursive":
380 - default:
381 - err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
382 - return err
388 + mode, ok := pin.StringToMode(typeStr)
389 + if !ok {
390 + return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
391 }
392
393 // For backward compatibility, we accumulate the pins in the same output type as before.
@@ -397,7 +405,7 @@ Example:
405 }
406
407 if len(req.Arguments) > 0 {
400 - err = pinLsKeys(req, typeStr, api, emit)
408 + err = pinLsKeys(req, mode, displayNames || name != "", n.Pinning, api, emit)
409 } else {
410 err = pinLsAll(req, typeStr, displayNames || name != "", name, api, emit)
411 }
@@ -482,23 +490,14 @@ type PinLsObject struct {
490 Type string `json:",omitempty"`
491 }
492
485 -func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
493 +func pinLsKeys(req *cmds.Request, mode pin.Mode, displayNames bool, pinner pin.Pinner, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error {
494 enc, err := cmdenv.GetCidEncoder(req)
495 if err != nil {
496 return err
497 }
498
491 - switch typeStr {
492 - case "all", "direct", "indirect", "recursive":
493 - default:
494 - return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
495 - }
496 -
497 - opt, err := options.Pin.IsPinned.Type(typeStr)
498 - if err != nil {
499 - panic("unhandled pin type")
500 - }
501 -
499 + // Collect CIDs to check
500 + cids := make([]cid.Cid, 0, len(req.Arguments))
501 for _, p := range req.Arguments {
502 p, err := cmdutils.PathOrCidPath(p)
503 if err != nil {
@@ -510,25 +509,31 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu
509 return err
510 }
511
513 - pinType, pinned, err := api.Pin().IsPinned(req.Context, rp, opt)
514 - if err != nil {
515 - return err
516 - }
512 + cids = append(cids, rp.RootCid())
513 + }
514
518 - if !pinned {
519 - return fmt.Errorf("path '%s' is not pinned", p)
515 + // Check pins using the new type-specific method
516 + pinned, err := pinner.CheckIfPinnedWithType(req.Context, mode, displayNames, cids...)
517 + if err != nil {
518 + return err
519 + }
520 +
521 + // Process results
522 + for i, p := range pinned {
523 + if !p.Pinned() {
524 + return fmt.Errorf("path '%s' is not pinned", req.Arguments[i])
525 }
526
522 - switch pinType {
523 - case "direct", "indirect", "recursive", "internal":
524 - default:
525 - pinType = "indirect through " + pinType
527 + pinType, _ := pin.ModeToString(p.Mode)
528 + if p.Mode == pin.Indirect && p.Via.Defined() {
529 + pinType = "indirect through " + enc.Encode(p.Via)
530 }
531
532 err = emit(PinLsOutputWrapper{
533 PinLsObject: PinLsObject{
534 Type: pinType,
531 - Cid: enc.Encode(rp.RootCid()),
535 + Cid: enc.Encode(cids[i]),
536 + Name: p.Name,
537 },
538 })
539 if err != nil {
@@ -545,11 +550,9 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, name string, api
550 return err
551 }
552
548 - switch typeStr {
549 - case "all", "direct", "indirect", "recursive":
550 - default:
551 - err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
552 - return err
553 + _, ok := pin.StringToMode(typeStr)
554 + if !ok {
555 + return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr)
556 }
557
558 opt, err := options.Pin.Ls.Type(typeStr)
core/coreiface/tests/pin.go
+141
@@ -12,6 +12,7 @@ import (
12 ipld "github.com/ipfs/go-ipld-format"
13 iface "github.com/ipfs/kubo/core/coreiface"
14 opt "github.com/ipfs/kubo/core/coreiface/options"
15 + "github.com/stretchr/testify/require"
16 )
17
18 func (tp *TestSuite) TestPin(t *testing.T) {
@@ -28,6 +29,7 @@ func (tp *TestSuite) TestPin(t *testing.T) {
29 t.Run("TestPinLsIndirect", tp.TestPinLsIndirect)
30 t.Run("TestPinLsPrecedence", tp.TestPinLsPrecedence)
31 t.Run("TestPinIsPinned", tp.TestPinIsPinned)
32 + t.Run("TestPinNames", tp.TestPinNames)
33 }
34
35 func (tp *TestSuite) TestPinAdd(t *testing.T) {
@@ -580,6 +582,145 @@ func assertIsPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path
582 }
583 }
584
585 +func (tp *TestSuite) TestPinNames(t *testing.T) {
586 + ctx, cancel := context.WithCancel(context.Background())
587 + defer cancel()
588 + api, err := tp.makeAPI(t, ctx)
589 + require.NoError(t, err)
590 +
591 + // Create test content
592 + p1, err := api.Unixfs().Add(ctx, strFile("content1")())
593 + require.NoError(t, err)
594 +
595 + p2, err := api.Unixfs().Add(ctx, strFile("content2")())
596 + require.NoError(t, err)
597 +
598 + p3, err := api.Unixfs().Add(ctx, strFile("content3")())
599 + require.NoError(t, err)
600 +
601 + p4, err := api.Unixfs().Add(ctx, strFile("content4")())
602 + require.NoError(t, err)
603 +
604 + // Test 1: Pin with name
605 + err = api.Pin().Add(ctx, p1, opt.Pin.Name("test-pin-1"))
606 + require.NoError(t, err, "failed to add pin with name")
607 +
608 + // Test 2: Pin without name
609 + err = api.Pin().Add(ctx, p2)
610 + require.NoError(t, err, "failed to add pin without name")
611 +
612 + // Test 3: List pins with detailed option to get names
613 + pins := make(chan iface.Pin)
614 + go func() {
615 + err = api.Pin().Ls(ctx, pins, opt.Pin.Ls.Detailed(true))
616 + }()
617 +
618 + pinMap := make(map[string]string)
619 + for pin := range pins {
620 + pinMap[pin.Path().String()] = pin.Name()
621 + }
622 + require.NoError(t, err, "failed to list pins with names")
623 +
624 + // Verify pin names
625 + name1, ok := pinMap[p1.String()]
626 + require.True(t, ok, "pin for %s not found", p1)
627 + require.Equal(t, "test-pin-1", name1, "unexpected pin name for %s", p1)
628 +
629 + name2, ok := pinMap[p2.String()]
630 + require.True(t, ok, "pin for %s not found", p2)
631 + require.Empty(t, name2, "expected empty pin name for %s, got '%s'", p2, name2)
632 +
633 + // Test 4: Pin update preserves name
634 + err = api.Pin().Add(ctx, p3, opt.Pin.Name("updatable-pin"))
635 + require.NoError(t, err, "failed to add pin with name for update test")
636 +
637 + err = api.Pin().Update(ctx, p3, p4)
638 + require.NoError(t, err, "failed to update pin")
639 +
640 + // Verify name was preserved after update
641 + pins2 := make(chan iface.Pin)
642 + go func() {
643 + err = api.Pin().Ls(ctx, pins2, opt.Pin.Ls.Detailed(true))
644 + }()
645 +
646 + updatedPinMap := make(map[string]string)
647 + for pin := range pins2 {
648 + updatedPinMap[pin.Path().String()] = pin.Name()
649 + }
650 + require.NoError(t, err, "failed to list pins after update")
651 +
652 + // Old pin should not exist
653 + _, oldExists := updatedPinMap[p3.String()]
654 + require.False(t, oldExists, "old pin %s should not exist after update", p3)
655 +
656 + // New pin should have the preserved name
657 + name4, ok := updatedPinMap[p4.String()]
658 + require.True(t, ok, "updated pin for %s not found", p4)
659 + require.Equal(t, "updatable-pin", name4, "pin name not preserved after update from %s to %s", p3, p4)
660 +
661 + // Test 5: Re-pinning with different name updates the name
662 + err = api.Pin().Add(ctx, p1, opt.Pin.Name("new-name-for-p1"))
663 + require.NoError(t, err, "failed to re-pin with new name")
664 +
665 + // Verify name was updated
666 + pins3 := make(chan iface.Pin)
667 + go func() {
668 + err = api.Pin().Ls(ctx, pins3, opt.Pin.Ls.Detailed(true))
669 + }()
670 +
671 + repinMap := make(map[string]string)
672 + for pin := range pins3 {
673 + repinMap[pin.Path().String()] = pin.Name()
674 + }
675 + require.NoError(t, err, "failed to list pins after re-pin")
676 +
677 + rePinnedName, ok := repinMap[p1.String()]
678 + require.True(t, ok, "re-pinned content %s not found", p1)
679 + require.Equal(t, "new-name-for-p1", rePinnedName, "pin name not updated after re-pinning %s", p1)
680 +
681 + // Test 6: Direct pin with name
682 + p5, err := api.Unixfs().Add(ctx, strFile("direct-content")())
683 + require.NoError(t, err)
684 +
685 + err = api.Pin().Add(ctx, p5, opt.Pin.Recursive(false), opt.Pin.Name("direct-pin-name"))
686 + require.NoError(t, err, "failed to add direct pin with name")
687 +
688 + // Verify direct pin has name
689 + directPins := make(chan iface.Pin)
690 + typeOpt, err := opt.Pin.Ls.Type("direct")
691 + require.NoError(t, err, "failed to create type option")
692 + go func() {
693 + err = api.Pin().Ls(ctx, directPins, typeOpt, opt.Pin.Ls.Detailed(true))
694 + }()
695 +
696 + directPinMap := make(map[string]string)
697 + for pin := range directPins {
698 + directPinMap[pin.Path().String()] = pin.Name()
699 + }
700 + require.NoError(t, err, "failed to list direct pins")
701 +
702 + directName, ok := directPinMap[p5.String()]
703 + require.True(t, ok, "direct pin %s not found", p5)
704 + require.Equal(t, "direct-pin-name", directName, "unexpected name for direct pin %s", p5)
705 +
706 + // Test 7: List without detailed option doesn't return names
707 + pinsNoDetails := make(chan iface.Pin)
708 + go func() {
709 + err = api.Pin().Ls(ctx, pinsNoDetails)
710 + }()
711 +
712 + noDetailsMap := make(map[string]string)
713 + for pin := range pinsNoDetails {
714 + noDetailsMap[pin.Path().String()] = pin.Name()
715 + }
716 + require.NoError(t, err, "failed to list pins without detailed option")
717 +
718 + // All names should be empty without detailed option
719 + for path, name := range noDetailsMap {
720 + require.Empty(t, name, "expected empty name for %s without detailed option, got '%s'", path, name)
721 + }
722 +}
723 +
724 func assertNotPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path.Path) {
725 t.Helper()
726
docs/changelogs/v0.38.md
+4
@@ -64,6 +64,10 @@ Gateway error pages now provide more actionable information during content retri
64 > - **Enhanced error details**: Timeout errors now display the retrieval phase where failure occurred (e.g., "connecting to providers", "fetching data") and up to 3 peer IDs that were attempted but couldn't deliver the content, making it easier to diagnose network or provider issues.
65 > - **Retry button on all error pages**: Every gateway error page now includes a retry button for quick page refresh without manual URL re-entry.
66
67 +#### 📌 Pin name improvements
68 +
69 +`ipfs pin ls <cid> --names` now correctly returns pin names for specific CIDs ([#10649](https://github.com/ipfs/kubo/issues/10649), [boxo#1035](https://github.com/ipfs/boxo/pull/1035)), and RPC no longer incorrectly returns names from other pins ([#10966](https://github.com/ipfs/kubo/pull/10966)).
70 +
71 #### 🛠️ Identity CID size enforcement and `ipfs files write` fixes
72
73 **Identity CID size limits are now enforced**
docs/examples/kubo-as-a-library/go.mod
+12 -11
@@ -7,7 +7,7 @@ go 1.25
7 replace github.com/ipfs/kubo => ./../../..
8
9 require (
10 - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3
10 + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f
11 github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12 github.com/libp2p/go-libp2p v0.43.0
13 github.com/multiformats/go-multiaddr v0.16.1
@@ -73,10 +73,10 @@ require (
73 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 // indirect
74 github.com/ipfs/bbloom v0.0.4 // indirect
75 github.com/ipfs/go-bitfield v1.1.0 // indirect
76 - github.com/ipfs/go-block-format v0.2.2 // indirect
76 + github.com/ipfs/go-block-format v0.2.3 // indirect
77 github.com/ipfs/go-cid v0.5.0 // indirect
78 github.com/ipfs/go-cidutil v0.1.0 // indirect
79 - github.com/ipfs/go-datastore v0.8.4 // indirect
79 + github.com/ipfs/go-datastore v0.9.0 // indirect
80 github.com/ipfs/go-ds-badger v0.3.4 // indirect
81 github.com/ipfs/go-ds-flatfs v0.5.5 // indirect
82 github.com/ipfs/go-ds-leveldb v0.5.2 // indirect
@@ -88,14 +88,14 @@ require (
88 github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
89 github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
90 github.com/ipfs/go-ipld-cbor v0.2.1 // indirect
91 - github.com/ipfs/go-ipld-format v0.6.2 // indirect
91 + github.com/ipfs/go-ipld-format v0.6.3 // indirect
92 github.com/ipfs/go-ipld-git v0.1.1 // indirect
93 github.com/ipfs/go-ipld-legacy v0.2.2 // indirect
94 github.com/ipfs/go-log/v2 v2.8.1 // indirect
95 github.com/ipfs/go-metrics-interface v0.3.0 // indirect
96 github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
97 github.com/ipfs/go-test v0.2.3 // indirect
98 - github.com/ipfs/go-unixfsnode v1.10.1 // indirect
98 + github.com/ipfs/go-unixfsnode v1.10.2 // indirect
99 github.com/ipld/go-car/v2 v2.15.0 // indirect
100 github.com/ipld/go-codec-dagpb v1.7.0 // indirect
101 github.com/ipld/go-ipld-prime v0.21.0 // indirect
@@ -209,15 +209,16 @@ require (
209 go.uber.org/zap/exp v0.3.0 // indirect
210 go.yaml.in/yaml/v2 v2.4.2 // indirect
211 go4.org v0.0.0-20230225012048-214862532bf5 // indirect
212 - golang.org/x/crypto v0.41.0 // indirect
213 - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
214 - golang.org/x/mod v0.27.0 // indirect
215 - golang.org/x/net v0.43.0 // indirect
212 + golang.org/x/crypto v0.42.0 // indirect
213 + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
214 + golang.org/x/mod v0.28.0 // indirect
215 + golang.org/x/net v0.44.0 // indirect
216 golang.org/x/sync v0.17.0 // indirect
217 golang.org/x/sys v0.36.0 // indirect
218 - golang.org/x/text v0.28.0 // indirect
218 + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect
219 + golang.org/x/text v0.29.0 // indirect
220 golang.org/x/time v0.12.0 // indirect
220 - golang.org/x/tools v0.36.0 // indirect
221 + golang.org/x/tools v0.37.0 // indirect
222 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
223 gonum.org/v1/gonum v0.16.0 // indirect
224 google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
docs/examples/kubo-as-a-library/go.sum
+24 -22
@@ -289,13 +289,13 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
289 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
290 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
291 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
292 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
293 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
292 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg=
293 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo=
294 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
295 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
296 github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
297 -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=
298 -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8=
297 +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk=
298 +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA=
299 github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
300 github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
301 github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
@@ -305,8 +305,8 @@ github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q
305 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
306 github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
307 github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
308 -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
309 -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
308 +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w=
309 +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
310 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
311 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
312 github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -340,8 +340,8 @@ github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyB
340 github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
341 github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E=
342 github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A=
343 -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU=
344 -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk=
343 +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8=
344 +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk=
345 github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
346 github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
347 github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ=
@@ -357,8 +357,8 @@ github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8
357 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
358 github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
359 github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
360 -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
361 -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
360 +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8=
361 +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg=
362 github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
363 github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
364 github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
@@ -840,8 +840,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
840 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
841 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
842 golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
843 -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
844 -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
843 +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
844 +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
845 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
846 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
847 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -850,8 +850,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
850 golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
851 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
852 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
853 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
854 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
853 +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
854 +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
855 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
856 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
857 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -874,8 +874,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
874 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
875 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
876 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
877 -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
878 -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
877 +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
878 +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
879 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
880 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
881 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -911,8 +911,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
911 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
912 golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
913 golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
914 -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
915 -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
914 +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
915 +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
916 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
917 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
918 golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -981,6 +981,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
981 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
982 golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
983 golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
984 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
985 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
986 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
987 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
988 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1000,8 +1002,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
1002 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
1003 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
1004 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1003 -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
1004 -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
1005 +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
1006 +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
1007 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1008 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1009 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1042,8 +1044,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
1044 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
1045 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
1046 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
1045 -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
1046 -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
1047 +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
1048 +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
1049 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1050 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1051 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
go.mod
+13 -12
@@ -22,11 +22,11 @@ require (
22 github.com/hashicorp/go-version v1.7.0
23 github.com/ipfs-shipyard/nopfs v0.0.14
24 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
25 - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3
26 - github.com/ipfs/go-block-format v0.2.2
25 + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f
26 + github.com/ipfs/go-block-format v0.2.3
27 github.com/ipfs/go-cid v0.5.0
28 github.com/ipfs/go-cidutil v0.1.0
29 - github.com/ipfs/go-datastore v0.8.4
29 + github.com/ipfs/go-datastore v0.9.0
30 github.com/ipfs/go-detect-race v0.0.1
31 github.com/ipfs/go-ds-badger v0.3.4
32 github.com/ipfs/go-ds-flatfs v0.5.5
@@ -36,14 +36,14 @@ require (
36 github.com/ipfs/go-fs-lock v0.1.1
37 github.com/ipfs/go-ipfs-cmds v0.15.0
38 github.com/ipfs/go-ipld-cbor v0.2.1
39 - github.com/ipfs/go-ipld-format v0.6.2
39 + github.com/ipfs/go-ipld-format v0.6.3
40 github.com/ipfs/go-ipld-git v0.1.1
41 github.com/ipfs/go-ipld-legacy v0.2.2
42 github.com/ipfs/go-log/v2 v2.8.1
43 github.com/ipfs/go-metrics-interface v0.3.0
44 github.com/ipfs/go-metrics-prometheus v0.1.0
45 github.com/ipfs/go-test v0.2.3
46 - github.com/ipfs/go-unixfsnode v1.10.1
46 + github.com/ipfs/go-unixfsnode v1.10.2
47 github.com/ipld/go-car/v2 v2.15.0
48 github.com/ipld/go-codec-dagpb v1.7.0
49 github.com/ipld/go-ipld-prime v0.21.0
@@ -87,9 +87,9 @@ require (
87 go.uber.org/dig v1.19.0
88 go.uber.org/fx v1.24.0
89 go.uber.org/zap v1.27.0
90 - golang.org/x/crypto v0.41.0
91 - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
92 - golang.org/x/mod v0.27.0
90 + golang.org/x/crypto v0.42.0
91 + golang.org/x/exp v0.0.0-20250911091902-df9299821621
92 + golang.org/x/mod v0.28.0
93 golang.org/x/sync v0.17.0
94 golang.org/x/sys v0.36.0
95 google.golang.org/protobuf v1.36.9
@@ -254,12 +254,13 @@ require (
254 go.uber.org/zap/exp v0.3.0 // indirect
255 go.yaml.in/yaml/v2 v2.4.2 // indirect
256 go4.org v0.0.0-20230225012048-214862532bf5 // indirect
257 - golang.org/x/net v0.43.0 // indirect
257 + golang.org/x/net v0.44.0 // indirect
258 golang.org/x/oauth2 v0.31.0 // indirect
259 - golang.org/x/term v0.34.0 // indirect
260 - golang.org/x/text v0.28.0 // indirect
259 + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect
260 + golang.org/x/term v0.35.0 // indirect
261 + golang.org/x/text v0.29.0 // indirect
262 golang.org/x/time v0.12.0 // indirect
262 - golang.org/x/tools v0.36.0 // indirect
263 + golang.org/x/tools v0.37.0 // indirect
264 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
265 gonum.org/v1/gonum v0.16.0 // indirect
266 google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
go.sum
+26 -24
@@ -356,13 +356,13 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
356 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
357 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
358 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
359 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
360 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
359 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg=
360 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo=
361 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
362 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
363 github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
364 -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=
365 -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8=
364 +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk=
365 +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA=
366 github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
367 github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
368 github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
@@ -372,8 +372,8 @@ github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q
372 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
373 github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
374 github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
375 -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
376 -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
375 +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w=
376 +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
377 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
378 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
379 github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -409,8 +409,8 @@ github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyB
409 github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
410 github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E=
411 github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A=
412 -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU=
413 -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk=
412 +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8=
413 +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk=
414 github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
415 github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
416 github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ=
@@ -428,8 +428,8 @@ github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8
428 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
429 github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
430 github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
431 -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
432 -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
431 +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8=
432 +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg=
433 github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
434 github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
435 github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
@@ -1007,8 +1007,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
1007 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
1008 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
1009 golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
1010 -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
1011 -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
1010 +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
1011 +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
1012 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
1013 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
1014 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1019,8 +1019,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
1019 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
1020 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
1021 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
1022 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
1023 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
1022 +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
1023 +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
1024 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
1025 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
1026 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -1044,8 +1044,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1044 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
1045 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
1046 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
1047 -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
1048 -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
1047 +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
1048 +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
1049 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
1050 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
1051 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1097,8 +1097,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
1097 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
1098 golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
1099 golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
1100 -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
1101 -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
1100 +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
1101 +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
1102 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
1103 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
1104 golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1196,6 +1196,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1196 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1197 golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
1198 golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1199 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
1200 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
1201 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
1202 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
1203 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1204,8 +1206,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
1206 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
1207 golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
1208 golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
1207 -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
1208 -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
1209 +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
1210 +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
1211 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1212 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1213 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1217,8 +1219,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
1219 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
1220 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
1221 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1220 -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
1221 -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
1222 +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
1223 +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
1224 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1225 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1226 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1276,8 +1278,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
1278 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
1279 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
1280 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
1279 -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
1280 -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
1281 +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
1282 +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
1283 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1284 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1285 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
test/cli/pin_ls_names_test.go new
+534
@@ -0,0 +1,534 @@
1 +package cli
2 +
3 +import (
4 + "encoding/json"
5 + "fmt"
6 + "os"
7 + "path/filepath"
8 + "strings"
9 + "testing"
10 +
11 + "github.com/ipfs/kubo/test/cli/harness"
12 + "github.com/stretchr/testify/require"
13 +)
14 +
15 +// pinInfo represents the JSON structure for pin ls output
16 +type pinInfo struct {
17 + Type string `json:"Type"`
18 + Name string `json:"Name"`
19 +}
20 +
21 +// pinLsJSON represents the JSON output structure for pin ls command
22 +type pinLsJSON struct {
23 + Keys map[string]pinInfo `json:"Keys"`
24 +}
25 +
26 +// Helper function to initialize a test node with daemon
27 +func setupTestNode(t *testing.T) *harness.Node {
28 + t.Helper()
29 + node := harness.NewT(t).NewNode().Init()
30 + node.StartDaemon("--offline")
31 + return node
32 +}
33 +
34 +// Helper function to assert pin name and CID are present in output
35 +func assertPinOutput(t *testing.T, output, cid, pinName string) {
36 + t.Helper()
37 + require.Contains(t, output, pinName, "pin name '%s' not found in output: %s", pinName, output)
38 + require.Contains(t, output, cid, "CID %s not found in output: %s", cid, output)
39 +}
40 +
41 +// Helper function to assert CID is present but name is not
42 +func assertCIDOnly(t *testing.T, output, cid string) {
43 + t.Helper()
44 + require.Contains(t, output, cid, "CID %s not found in output: %s", cid, output)
45 +}
46 +
47 +// Helper function to assert neither CID nor name are present
48 +func assertNotPresent(t *testing.T, output, cid, pinName string) {
49 + t.Helper()
50 + require.NotContains(t, output, cid, "CID %s should not be present in output: %s", cid, output)
51 + require.NotContains(t, output, pinName, "pin name '%s' should not be present in output: %s", pinName, output)
52 +}
53 +
54 +// Test that pin ls returns names when querying specific CIDs with --names flag
55 +func TestPinLsWithNamesForSpecificCIDs(t *testing.T) {
56 + t.Parallel()
57 +
58 + t.Run("pin ls with specific CID returns name", func(t *testing.T) {
59 + t.Parallel()
60 + node := setupTestNode(t)
61 +
62 + // Add content without pinning
63 + cidA := node.IPFSAddStr("content A", "--pin=false")
64 + cidB := node.IPFSAddStr("content B", "--pin=false")
65 + cidC := node.IPFSAddStr("content C", "--pin=false")
66 +
67 + // Pin with names
68 + node.IPFS("pin", "add", "--name=pin-a", cidA)
69 + node.IPFS("pin", "add", "--name=pin-b", cidB)
70 + node.IPFS("pin", "add", cidC) // No name
71 +
72 + // Test: pin ls <cid> --names should return the name
73 + res := node.IPFS("pin", "ls", cidA, "--names")
74 + assertPinOutput(t, res.Stdout.String(), cidA, "pin-a")
75 +
76 + res = node.IPFS("pin", "ls", cidB, "--names")
77 + assertPinOutput(t, res.Stdout.String(), cidB, "pin-b")
78 +
79 + // Test: pin without name should work
80 + res = node.IPFS("pin", "ls", cidC, "--names")
81 + output := res.Stdout.String()
82 + assertCIDOnly(t, output, cidC)
83 + require.Contains(t, output, "recursive", "pin type 'recursive' not found for CID %s in output: %s", cidC, output)
84 +
85 + // Test: without --names flag, no names returned
86 + res = node.IPFS("pin", "ls", cidA)
87 + output = res.Stdout.String()
88 + require.NotContains(t, output, "pin-a", "pin name 'pin-a' should not be present without --names flag, but found in: %s", output)
89 + assertCIDOnly(t, output, cidA)
90 + })
91 +
92 + t.Run("pin ls with multiple CIDs returns names", func(t *testing.T) {
93 + t.Parallel()
94 + node := setupTestNode(t)
95 +
96 + // Create test content
97 + cidA := node.IPFSAddStr("multi A", "--pin=false")
98 + cidB := node.IPFSAddStr("multi B", "--pin=false")
99 +
100 + // Pin with names
101 + node.IPFS("pin", "add", "--name=multi-pin-a", cidA)
102 + node.IPFS("pin", "add", "--name=multi-pin-b", cidB)
103 +
104 + // Test multiple CIDs at once
105 + res := node.IPFS("pin", "ls", cidA, cidB, "--names")
106 + output := res.Stdout.String()
107 + assertPinOutput(t, output, cidA, "multi-pin-a")
108 + assertPinOutput(t, output, cidB, "multi-pin-b")
109 + })
110 +
111 + t.Run("pin ls without CID lists all pins with names", func(t *testing.T) {
112 + t.Parallel()
113 + node := setupTestNode(t)
114 +
115 + // Create and pin content with names
116 + cidA := node.IPFSAddStr("list all A", "--pin=false")
117 + cidB := node.IPFSAddStr("list all B", "--pin=false")
118 + cidC := node.IPFSAddStr("list all C", "--pin=false")
119 +
120 + node.IPFS("pin", "add", "--name=all-pin-a", cidA)
121 + node.IPFS("pin", "add", "--name=all-pin-b", "--recursive=false", cidB)
122 + node.IPFS("pin", "add", cidC) // No name
123 +
124 + // Test: pin ls --names (without CID) should list all pins with their names
125 + res := node.IPFS("pin", "ls", "--names")
126 + output := res.Stdout.String()
127 +
128 + // Should contain all pins with their names
129 + assertPinOutput(t, output, cidA, "all-pin-a")
130 + assertPinOutput(t, output, cidB, "all-pin-b")
131 + assertCIDOnly(t, output, cidC)
132 +
133 + // Pin C should appear but without a name (just type)
134 + lines := strings.Split(output, "\n")
135 + for _, line := range lines {
136 + if strings.Contains(line, cidC) {
137 + // Should have CID and type but no name
138 + require.Contains(t, line, "recursive", "pin type 'recursive' not found for unnamed pin %s in line: %s", cidC, line)
139 + require.NotContains(t, line, "all-pin", "pin name should not be present for unnamed pin %s, but found in line: %s", cidC, line)
140 + }
141 + }
142 + })
143 +
144 + t.Run("pin ls --type with --names", func(t *testing.T) {
145 + t.Parallel()
146 + node := setupTestNode(t)
147 +
148 + // Create test content
149 + cidDirect := node.IPFSAddStr("direct content", "--pin=false")
150 + cidRecursive := node.IPFSAddStr("recursive content", "--pin=false")
151 +
152 + // Create a DAG for indirect testing
153 + childCid := node.IPFSAddStr("child for indirect", "--pin=false")
154 + parentContent := fmt.Sprintf(`{"link": "/ipfs/%s"}`, childCid)
155 + parentCid := node.PipeStrToIPFS(parentContent, "dag", "put", "--input-codec=json", "--store-codec=dag-cbor").Stdout.Trimmed()
156 +
157 + // Pin with different types and names
158 + node.IPFS("pin", "add", "--name=direct-pin", "--recursive=false", cidDirect)
159 + node.IPFS("pin", "add", "--name=recursive-pin", cidRecursive)
160 + node.IPFS("pin", "add", "--name=parent-pin", parentCid)
161 +
162 + // Test: --type=direct --names
163 + res := node.IPFS("pin", "ls", "--type=direct", "--names")
164 + output := res.Stdout.String()
165 + assertPinOutput(t, output, cidDirect, "direct-pin")
166 + assertNotPresent(t, output, cidRecursive, "recursive-pin")
167 +
168 + // Test: --type=recursive --names
169 + res = node.IPFS("pin", "ls", "--type=recursive", "--names")
170 + output = res.Stdout.String()
171 + assertPinOutput(t, output, cidRecursive, "recursive-pin")
172 + assertPinOutput(t, output, parentCid, "parent-pin")
173 + assertNotPresent(t, output, cidDirect, "direct-pin")
174 +
175 + // Test: --type=indirect with proper directory structure
176 + // Create a directory with a file for indirect pin testing
177 + dirPath := t.TempDir()
178 + require.NoError(t, os.WriteFile(filepath.Join(dirPath, "file.txt"), []byte("test content"), 0644))
179 +
180 + // Add directory recursively
181 + dirAddRes := node.IPFS("add", "-r", "-q", dirPath)
182 + dirCidStr := strings.TrimSpace(dirAddRes.Stdout.Lines()[len(dirAddRes.Stdout.Lines())-1])
183 +
184 + // Add file separately without pinning to get its CID
185 + fileAddRes := node.IPFS("add", "-q", "--pin=false", filepath.Join(dirPath, "file.txt"))
186 + fileCidStr := strings.TrimSpace(fileAddRes.Stdout.String())
187 +
188 + // Check if file shows as indirect
189 + res = node.IPFS("pin", "ls", "--type=indirect", fileCidStr)
190 + output = res.Stdout.String()
191 + require.Contains(t, output, fileCidStr, "indirect pin CID %s not found in output: %s", fileCidStr, output)
192 + require.Contains(t, output, "indirect through "+dirCidStr, "indirect relationship not found for CID %s through %s in output: %s", fileCidStr, dirCidStr, output)
193 +
194 + // Test: --type=all --names
195 + res = node.IPFS("pin", "ls", "--type=all", "--names")
196 + output = res.Stdout.String()
197 + assertPinOutput(t, output, cidDirect, "direct-pin")
198 + assertPinOutput(t, output, cidRecursive, "recursive-pin")
199 + assertPinOutput(t, output, parentCid, "parent-pin")
200 + // Indirect pins are included in --type=all output
201 + })
202 +
203 + t.Run("pin ls JSON output with names", func(t *testing.T) {
204 + t.Parallel()
205 + node := setupTestNode(t)
206 +
207 + // Add and pin content with name
208 + cidA := node.IPFSAddStr("json content", "--pin=false")
209 + node.IPFS("pin", "add", "--name=json-pin", cidA)
210 +
211 + // Test JSON output with specific CID
212 + res := node.IPFS("pin", "ls", cidA, "--names", "--enc=json")
213 + var pinOutput pinLsJSON
214 + err := json.Unmarshal([]byte(res.Stdout.String()), &pinOutput)
215 + require.NoError(t, err, "failed to unmarshal JSON output: %s", res.Stdout.String())
216 +
217 + pinData, ok := pinOutput.Keys[cidA]
218 + require.True(t, ok, "CID %s should be in Keys map, got: %+v", cidA, pinOutput.Keys)
219 + require.Equal(t, "recursive", pinData.Type, "expected pin type 'recursive', got '%s'", pinData.Type)
220 + require.Equal(t, "json-pin", pinData.Name, "expected pin name 'json-pin', got '%s'", pinData.Name)
221 +
222 + // Without names flag
223 + res = node.IPFS("pin", "ls", cidA, "--enc=json")
224 + err = json.Unmarshal([]byte(res.Stdout.String()), &pinOutput)
225 + require.NoError(t, err, "failed to unmarshal JSON output: %s", res.Stdout.String())
226 +
227 + pinData, ok = pinOutput.Keys[cidA]
228 + require.True(t, ok, "CID %s should be in Keys map, got: %+v", cidA, pinOutput.Keys)
229 + // Name should be empty without --names flag
230 + require.Equal(t, "", pinData.Name, "pin name should be empty without --names flag, got '%s'", pinData.Name)
231 +
232 + // Test JSON output without CID (list all)
233 + res = node.IPFS("pin", "ls", "--names", "--enc=json")
234 + var listOutput pinLsJSON
235 + err = json.Unmarshal([]byte(res.Stdout.String()), &listOutput)
236 + require.NoError(t, err, "failed to unmarshal JSON list output: %s", res.Stdout.String())
237 + // Should have at least one pin (the one we just added)
238 + require.NotEmpty(t, listOutput.Keys, "pin list should not be empty")
239 + // Check that our pin is in the list
240 + pinData, ok = listOutput.Keys[cidA]
241 + require.True(t, ok, "our pin with CID %s should be in the list, got: %+v", cidA, listOutput.Keys)
242 + require.Equal(t, "json-pin", pinData.Name, "expected pin name 'json-pin' in list, got '%s'", pinData.Name)
243 + })
244 +
245 + t.Run("direct and indirect pins with names", func(t *testing.T) {
246 + t.Parallel()
247 + node := setupTestNode(t)
248 +
249 + // Create a small DAG: parent -> child
250 + childCid := node.IPFSAddStr("child content", "--pin=false")
251 +
252 + // Create parent that references child
253 + parentContent := fmt.Sprintf(`{"link": "/ipfs/%s"}`, childCid)
254 + parentCid := node.PipeStrToIPFS(parentContent, "dag", "put", "--input-codec=json", "--store-codec=dag-cbor").Stdout.Trimmed()
255 +
256 + // Pin child directly with a name
257 + node.IPFS("pin", "add", "--name=direct-child", "--recursive=false", childCid)
258 +
259 + // Pin parent recursively with a name
260 + node.IPFS("pin", "add", "--name=recursive-parent", parentCid)
261 +
262 + // Check direct pin with specific CID
263 + res := node.IPFS("pin", "ls", "--type=direct", childCid, "--names")
264 + output := res.Stdout.String()
265 + require.Contains(t, output, "direct-child", "pin name 'direct-child' not found in output: %s", output)
266 + require.Contains(t, output, "direct", "pin type 'direct' not found in output: %s", output)
267 +
268 + // Check recursive pin with specific CID
269 + res = node.IPFS("pin", "ls", "--type=recursive", parentCid, "--names")
270 + output = res.Stdout.String()
271 + require.Contains(t, output, "recursive-parent", "pin name 'recursive-parent' not found in output: %s", output)
272 + require.Contains(t, output, "recursive", "pin type 'recursive' not found in output: %s", output)
273 +
274 + // Child is both directly pinned and indirectly pinned through parent
275 + // Both relationships are valid and can be checked
276 + })
277 +
278 + t.Run("pin update preserves name", func(t *testing.T) {
279 + t.Parallel()
280 + node := setupTestNode(t)
281 +
282 + // Create two pieces of content
283 + cidOld := node.IPFSAddStr("old content", "--pin=false")
284 + cidNew := node.IPFSAddStr("new content", "--pin=false")
285 +
286 + // Pin with name
287 + node.IPFS("pin", "add", "--name=my-pin", cidOld)
288 +
289 + // Update pin
290 + node.IPFS("pin", "update", cidOld, cidNew)
291 +
292 + // Check that new pin has the same name
293 + res := node.IPFS("pin", "ls", cidNew, "--names")
294 + require.Contains(t, res.Stdout.String(), "my-pin", "pin name 'my-pin' not preserved after update, output: %s", res.Stdout.String())
295 +
296 + // Old pin should not exist
297 + res = node.RunIPFS("pin", "ls", cidOld)
298 + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for unpinned CID, got %d", res.ExitCode())
299 + require.Contains(t, res.Stderr.String(), "is not pinned", "expected 'is not pinned' error for old CID %s, got: %s", cidOld, res.Stderr.String())
300 + })
301 +
302 + t.Run("pin ls with invalid CID returns error", func(t *testing.T) {
303 + t.Parallel()
304 + node := harness.NewT(t).NewNode().Init()
305 +
306 + res := node.RunIPFS("pin", "ls", "invalid-cid")
307 + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for invalid CID, got %d", res.ExitCode())
308 + require.Contains(t, res.Stderr.String(), "invalid", "expected 'invalid' in error message, got: %s", res.Stderr.String())
309 + })
310 +
311 + t.Run("pin ls with unpinned CID returns error", func(t *testing.T) {
312 + t.Parallel()
313 + node := setupTestNode(t)
314 +
315 + // Add content without pinning
316 + cid := node.IPFSAddStr("unpinned content", "--pin=false")
317 +
318 + res := node.RunIPFS("pin", "ls", cid)
319 + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for unpinned CID, got %d", res.ExitCode())
320 + require.Contains(t, res.Stderr.String(), "is not pinned", "expected 'is not pinned' error for CID %s, got: %s", cid, res.Stderr.String())
321 + })
322 +
323 + t.Run("pin with special characters in name", func(t *testing.T) {
324 + t.Parallel()
325 + node := setupTestNode(t)
326 +
327 + testCases := []struct {
328 + name string
329 + pinName string
330 + }{
331 + {"unicode", "test-📌-pin"},
332 + {"spaces", "test pin name"},
333 + {"special chars", "test!@#$%"},
334 + {"path-like", "test/pin/name"},
335 + {"dots", "test.pin.name"},
336 + {"long name", strings.Repeat("a", 255)},
337 + {"empty name", ""},
338 + }
339 +
340 + for _, tc := range testCases {
341 + t.Run(tc.name, func(t *testing.T) {
342 + cid := node.IPFSAddStr("content for "+tc.name, "--pin=false")
343 + node.IPFS("pin", "add", "--name="+tc.pinName, cid)
344 +
345 + res := node.IPFS("pin", "ls", cid, "--names")
346 + if tc.pinName != "" {
347 + require.Contains(t, res.Stdout.String(), tc.pinName,
348 + "pin name '%s' not found in output for test case '%s'", tc.pinName, tc.name)
349 + }
350 + })
351 + }
352 + })
353 +
354 + t.Run("concurrent pin operations with names", func(t *testing.T) {
355 + t.Parallel()
356 + node := setupTestNode(t)
357 +
358 + // Create multiple goroutines adding pins with names
359 + numPins := 10
360 + done := make(chan struct{}, numPins)
361 +
362 + for i := 0; i < numPins; i++ {
363 + go func(idx int) {
364 + defer func() { done <- struct{}{} }()
365 +
366 + content := fmt.Sprintf("concurrent content %d", idx)
367 + cid := node.IPFSAddStr(content, "--pin=false")
368 + pinName := fmt.Sprintf("concurrent-pin-%d", idx)
369 + node.IPFS("pin", "add", "--name="+pinName, cid)
370 + }(i)
371 + }
372 +
373 + // Wait for all goroutines
374 + for i := 0; i < numPins; i++ {
375 + <-done
376 + }
377 +
378 + // Verify all pins have correct names
379 + res := node.IPFS("pin", "ls", "--names")
380 + output := res.Stdout.String()
381 + for i := 0; i < numPins; i++ {
382 + pinName := fmt.Sprintf("concurrent-pin-%d", i)
383 + require.Contains(t, output, pinName,
384 + "concurrent pin name '%s' not found in output", pinName)
385 + }
386 + })
387 +
388 + t.Run("pin rm removes name association", func(t *testing.T) {
389 + t.Parallel()
390 + node := setupTestNode(t)
391 +
392 + // Add and pin with name
393 + cid := node.IPFSAddStr("content to remove", "--pin=false")
394 + node.IPFS("pin", "add", "--name=to-be-removed", cid)
395 +
396 + // Verify pin exists with name
397 + res := node.IPFS("pin", "ls", cid, "--names")
398 + require.Contains(t, res.Stdout.String(), "to-be-removed")
399 +
400 + // Remove pin
401 + node.IPFS("pin", "rm", cid)
402 +
403 + // Verify pin and name are gone
404 + res = node.RunIPFS("pin", "ls", cid)
405 + require.Equal(t, 1, res.ExitCode())
406 + require.Contains(t, res.Stderr.String(), "is not pinned")
407 + })
408 +
409 + t.Run("garbage collection preserves named pins", func(t *testing.T) {
410 + t.Parallel()
411 + node := setupTestNode(t)
412 +
413 + // Add content with and without pin names
414 + cidNamed := node.IPFSAddStr("named content", "--pin=false")
415 + cidUnnamed := node.IPFSAddStr("unnamed content", "--pin=false")
416 + cidUnpinned := node.IPFSAddStr("unpinned content", "--pin=false")
417 +
418 + node.IPFS("pin", "add", "--name=important-data", cidNamed)
419 + node.IPFS("pin", "add", cidUnnamed)
420 +
421 + // Run garbage collection
422 + node.IPFS("repo", "gc")
423 +
424 + // Named and unnamed pins should still exist
425 + res := node.IPFS("pin", "ls", cidNamed, "--names")
426 + require.Contains(t, res.Stdout.String(), "important-data")
427 +
428 + res = node.IPFS("pin", "ls", cidUnnamed)
429 + require.Contains(t, res.Stdout.String(), cidUnnamed)
430 +
431 + // Unpinned content should be gone (cat should fail)
432 + res = node.RunIPFS("cat", cidUnpinned)
433 + require.NotEqual(t, 0, res.ExitCode(), "unpinned content should be garbage collected")
434 + })
435 +
436 + t.Run("pin add with same name can be used for multiple pins", func(t *testing.T) {
437 + t.Parallel()
438 + node := setupTestNode(t)
439 +
440 + // Add two different pieces of content
441 + cid1 := node.IPFSAddStr("first content", "--pin=false")
442 + cid2 := node.IPFSAddStr("second content", "--pin=false")
443 +
444 + // Pin both with the same name - this is allowed
445 + node.IPFS("pin", "add", "--name=shared-name", cid1)
446 + node.IPFS("pin", "add", "--name=shared-name", cid2)
447 +
448 + // List all pins with names
449 + res := node.IPFS("pin", "ls", "--names")
450 + output := res.Stdout.String()
451 +
452 + // Both CIDs should be pinned
453 + require.Contains(t, output, cid1)
454 + require.Contains(t, output, cid2)
455 +
456 + // Both pins can have the same name
457 + lines := strings.Split(output, "\n")
458 + foundCid1WithName := false
459 + foundCid2WithName := false
460 + for _, line := range lines {
461 + if strings.Contains(line, cid1) && strings.Contains(line, "shared-name") {
462 + foundCid1WithName = true
463 + }
464 + if strings.Contains(line, cid2) && strings.Contains(line, "shared-name") {
465 + foundCid2WithName = true
466 + }
467 + }
468 + require.True(t, foundCid1WithName, "first pin should have the name")
469 + require.True(t, foundCid2WithName, "second pin should have the name")
470 + })
471 +
472 + t.Run("pin names persist across daemon restarts", func(t *testing.T) {
473 + t.Parallel()
474 + node := harness.NewT(t).NewNode().Init()
475 + node.StartDaemon("--offline")
476 +
477 + // Add content with pin name
478 + cid := node.IPFSAddStr("persistent content")
479 + node.IPFS("pin", "add", "--name=persistent-pin", cid)
480 +
481 + // Restart daemon
482 + node.StopDaemon()
483 + node.StartDaemon("--offline")
484 +
485 + // Check pin name persisted
486 + res := node.IPFS("pin", "ls", cid, "--names")
487 + require.Contains(t, res.Stdout.String(), "persistent-pin",
488 + "pin name should persist across daemon restarts")
489 +
490 + node.StopDaemon()
491 + })
492 +}
493 +
494 +// TestPinLsEdgeCases tests edge cases for pin ls command
495 +func TestPinLsEdgeCases(t *testing.T) {
496 + t.Parallel()
497 +
498 + t.Run("invalid pin type returns error", func(t *testing.T) {
499 + t.Parallel()
500 + node := setupTestNode(t)
501 + defer node.StopDaemon()
502 +
503 + // Try to list pins with invalid type
504 + res := node.RunIPFS("pin", "ls", "--type=invalid")
505 + require.NotEqual(t, 0, res.ExitCode())
506 + require.Contains(t, res.Stderr.String(), "invalid type 'invalid'")
507 + require.Contains(t, res.Stderr.String(), "must be one of {direct, indirect, recursive, all}")
508 + })
509 +
510 + t.Run("non-existent path returns proper error", func(t *testing.T) {
511 + t.Parallel()
512 + node := setupTestNode(t)
513 + defer node.StopDaemon()
514 +
515 + // Try to list a non-existent CID
516 + fakeCID := "QmNonExistent123456789"
517 + res := node.RunIPFS("pin", "ls", fakeCID)
518 + require.NotEqual(t, 0, res.ExitCode())
519 + })
520 +
521 + t.Run("unpinned CID returns not pinned error", func(t *testing.T) {
522 + t.Parallel()
523 + node := setupTestNode(t)
524 + defer node.StopDaemon()
525 +
526 + // Add content but don't pin it explicitly (it's just in blockstore)
527 + unpinnedCID := node.IPFSAddStr("unpinned content", "--pin=false")
528 +
529 + // Try to list specific unpinned CID
530 + res := node.RunIPFS("pin", "ls", unpinnedCID)
531 + require.NotEqual(t, 0, res.ExitCode())
532 + require.Contains(t, res.Stderr.String(), "is not pinned")
533 + })
534 +}
test/dependencies/go.mod
+12 -12
@@ -135,18 +135,18 @@ require (
135 github.com/huin/goupnp v1.3.0 // indirect
136 github.com/inconshreveable/mousetrap v1.1.0 // indirect
137 github.com/ipfs/bbloom v0.0.4 // indirect
138 - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 // indirect
138 + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f // indirect
139 github.com/ipfs/go-bitfield v1.1.0 // indirect
140 - github.com/ipfs/go-block-format v0.2.2 // indirect
140 + github.com/ipfs/go-block-format v0.2.3 // indirect
141 github.com/ipfs/go-cid v0.5.0 // indirect
142 - github.com/ipfs/go-datastore v0.8.4 // indirect
142 + github.com/ipfs/go-datastore v0.9.0 // indirect
143 github.com/ipfs/go-dsqueue v0.0.5 // indirect
144 github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
145 github.com/ipfs/go-ipld-cbor v0.2.1 // indirect
146 - github.com/ipfs/go-ipld-format v0.6.2 // indirect
146 + github.com/ipfs/go-ipld-format v0.6.3 // indirect
147 github.com/ipfs/go-ipld-legacy v0.2.2 // indirect
148 github.com/ipfs/go-metrics-interface v0.3.0 // indirect
149 - github.com/ipfs/go-unixfsnode v1.10.1 // indirect
149 + github.com/ipfs/go-unixfsnode v1.10.2 // indirect
150 github.com/ipfs/kubo v0.31.0 // indirect
151 github.com/ipld/go-car/v2 v2.15.0 // indirect
152 github.com/ipld/go-codec-dagpb v1.7.0 // indirect
@@ -327,17 +327,17 @@ require (
327 go.uber.org/zap v1.27.0 // indirect
328 go.uber.org/zap/exp v0.3.0 // indirect
329 go.yaml.in/yaml/v2 v2.4.2 // indirect
330 - golang.org/x/crypto v0.41.0 // indirect
331 - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
330 + golang.org/x/crypto v0.42.0 // indirect
331 + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
332 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
333 - golang.org/x/mod v0.27.0 // indirect
334 - golang.org/x/net v0.43.0 // indirect
333 + golang.org/x/mod v0.28.0 // indirect
334 + golang.org/x/net v0.44.0 // indirect
335 golang.org/x/sync v0.17.0 // indirect
336 golang.org/x/sys v0.36.0 // indirect
337 - golang.org/x/term v0.34.0 // indirect
338 - golang.org/x/text v0.28.0 // indirect
337 + golang.org/x/term v0.35.0 // indirect
338 + golang.org/x/text v0.29.0 // indirect
339 golang.org/x/time v0.12.0 // indirect
340 - golang.org/x/tools v0.36.0 // indirect
340 + golang.org/x/tools v0.37.0 // indirect
341 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
342 gonum.org/v1/gonum v0.16.0 // indirect
343 google.golang.org/protobuf v1.36.9 // indirect
test/dependencies/go.sum
+26 -24
@@ -332,18 +332,18 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
332 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
333 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
334 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
335 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
336 -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
335 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg=
336 +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo=
337 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
338 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
339 -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=
340 -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8=
339 +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk=
340 +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA=
341 github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
342 github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
343 github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q=
344 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
345 -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
346 -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
345 +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w=
346 +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
347 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
348 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
349 github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU=
@@ -360,8 +360,8 @@ github.com/ipfs/go-ipfs-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68Q
360 github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw=
361 github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E=
362 github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A=
363 -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU=
364 -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk=
363 +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8=
364 +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk=
365 github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ=
366 github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU=
367 github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
@@ -374,8 +374,8 @@ github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8
374 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
375 github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
376 github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
377 -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
378 -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
377 +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8=
378 +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg=
379 github.com/ipfs/hang-fds v0.1.0 h1:deBiFlWHsVGzJ0ZMaqscEqRM1r2O1rFZ59UiQXb1Xko=
380 github.com/ipfs/hang-fds v0.1.0/go.mod h1:29VLWOn3ftAgNNgXg/al7b11UzuQ+w7AwtCGcTaWkbM=
381 github.com/ipfs/iptb v1.4.1 h1:faXd3TKGPswbHyZecqqg6UfbES7RDjTKQb+6VFPKDUo=
@@ -913,11 +913,11 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
913 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
914 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
915 golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
916 -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
917 -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
916 +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
917 +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
918 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
919 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
920 -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
919 +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
920 +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
921 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
922 golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
923 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4=
@@ -938,8 +938,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
938 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
939 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
940 golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
941 -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
942 -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
941 +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
942 +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
943 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
944 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
945 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -967,8 +967,8 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
967 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
968 golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
969 golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
970 -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
971 -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
970 +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
971 +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
972 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
973 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
974 golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1020,6 +1020,8 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1020 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1021 golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
1022 golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1023 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
1024 +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
1025 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
1026 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1027 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -1031,8 +1033,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
1033 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
1034 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
1035 golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
1034 -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
1035 -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
1036 +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
1037 +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
1038 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1039 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
1040 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -1046,8 +1048,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
1048 golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
1049 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
1050 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1049 -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
1050 -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
1051 +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
1052 +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
1053 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1054 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
1055 golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
@@ -1078,8 +1080,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
1080 golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
1081 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
1082 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
1081 -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
1082 -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
1083 +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
1084 +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
1085 golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
1086 golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
1087 golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=