diff --git a/client/rpc/pin.go b/client/rpc/pin.go index f959728b1..10a9f38b6 100644 --- a/client/rpc/pin.go +++ b/client/rpc/pin.go @@ -52,8 +52,12 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp return err } - return api.core().Request("pin/add", p.String()). - Option("recursive", options.Recursive).Exec(ctx, nil) + req := api.core().Request("pin/add", p.String()). + Option("recursive", options.Recursive) + if options.Name != "" { + req = req.Option("name", options.Name) + } + return req.Exec(ctx, nil) } type pinLsObject struct { diff --git a/core/commands/pin/pin.go b/core/commands/pin/pin.go index 428a75b69..86fafa539 100644 --- a/core/commands/pin/pin.go +++ b/core/commands/pin/pin.go @@ -11,6 +11,7 @@ import ( bserv "github.com/ipfs/boxo/blockservice" offline "github.com/ipfs/boxo/exchange/offline" dag "github.com/ipfs/boxo/ipld/merkledag" + pin "github.com/ipfs/boxo/pinning/pinner" verifcid "github.com/ipfs/boxo/verifcid" cid "github.com/ipfs/go-cid" cidenc "github.com/ipfs/go-cidutil/cidenc" @@ -370,16 +371,23 @@ Example: return err } + n, err := cmdenv.GetNode(env) + if err != nil { + return err + } + + if n.Pinning == nil { + return fmt.Errorf("pinning service not available") + } + typeStr, _ := req.Options[pinTypeOptionName].(string) stream, _ := req.Options[pinStreamOptionName].(bool) displayNames, _ := req.Options[pinNamesOptionName].(bool) name, _ := req.Options[pinNameOptionName].(string) - switch typeStr { - case "all", "direct", "indirect", "recursive": - default: - err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) - return err + mode, ok := pin.StringToMode(typeStr) + if !ok { + return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) } // For backward compatibility, we accumulate the pins in the same output type as before. @@ -397,7 +405,7 @@ Example: } if len(req.Arguments) > 0 { - err = pinLsKeys(req, typeStr, api, emit) + err = pinLsKeys(req, mode, displayNames || name != "", n.Pinning, api, emit) } else { err = pinLsAll(req, typeStr, displayNames || name != "", name, api, emit) } @@ -482,23 +490,14 @@ type PinLsObject struct { Type string `json:",omitempty"` } -func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error { +func pinLsKeys(req *cmds.Request, mode pin.Mode, displayNames bool, pinner pin.Pinner, api coreiface.CoreAPI, emit func(value PinLsOutputWrapper) error) error { enc, err := cmdenv.GetCidEncoder(req) if err != nil { return err } - switch typeStr { - case "all", "direct", "indirect", "recursive": - default: - return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) - } - - opt, err := options.Pin.IsPinned.Type(typeStr) - if err != nil { - panic("unhandled pin type") - } - + // Collect CIDs to check + cids := make([]cid.Cid, 0, len(req.Arguments)) for _, p := range req.Arguments { p, err := cmdutils.PathOrCidPath(p) if err != nil { @@ -510,25 +509,31 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu return err } - pinType, pinned, err := api.Pin().IsPinned(req.Context, rp, opt) - if err != nil { - return err + cids = append(cids, rp.RootCid()) + } + + // Check pins using the new type-specific method + pinned, err := pinner.CheckIfPinnedWithType(req.Context, mode, displayNames, cids...) + if err != nil { + return err + } + + // Process results + for i, p := range pinned { + if !p.Pinned() { + return fmt.Errorf("path '%s' is not pinned", req.Arguments[i]) } - if !pinned { - return fmt.Errorf("path '%s' is not pinned", p) - } - - switch pinType { - case "direct", "indirect", "recursive", "internal": - default: - pinType = "indirect through " + pinType + pinType, _ := pin.ModeToString(p.Mode) + if p.Mode == pin.Indirect && p.Via.Defined() { + pinType = "indirect through " + enc.Encode(p.Via) } err = emit(PinLsOutputWrapper{ PinLsObject: PinLsObject{ Type: pinType, - Cid: enc.Encode(rp.RootCid()), + Cid: enc.Encode(cids[i]), + Name: p.Name, }, }) if err != nil { @@ -545,11 +550,9 @@ func pinLsAll(req *cmds.Request, typeStr string, detailed bool, name string, api return err } - switch typeStr { - case "all", "direct", "indirect", "recursive": - default: - err = fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) - return err + _, ok := pin.StringToMode(typeStr) + if !ok { + return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", typeStr) } opt, err := options.Pin.Ls.Type(typeStr) diff --git a/core/coreiface/tests/pin.go b/core/coreiface/tests/pin.go index 18f90c051..684e1e5a1 100644 --- a/core/coreiface/tests/pin.go +++ b/core/coreiface/tests/pin.go @@ -12,6 +12,7 @@ import ( ipld "github.com/ipfs/go-ipld-format" iface "github.com/ipfs/kubo/core/coreiface" opt "github.com/ipfs/kubo/core/coreiface/options" + "github.com/stretchr/testify/require" ) func (tp *TestSuite) TestPin(t *testing.T) { @@ -28,6 +29,7 @@ func (tp *TestSuite) TestPin(t *testing.T) { t.Run("TestPinLsIndirect", tp.TestPinLsIndirect) t.Run("TestPinLsPrecedence", tp.TestPinLsPrecedence) t.Run("TestPinIsPinned", tp.TestPinIsPinned) + t.Run("TestPinNames", tp.TestPinNames) } func (tp *TestSuite) TestPinAdd(t *testing.T) { @@ -580,6 +582,145 @@ func assertIsPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path } } +func (tp *TestSuite) TestPinNames(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + api, err := tp.makeAPI(t, ctx) + require.NoError(t, err) + + // Create test content + p1, err := api.Unixfs().Add(ctx, strFile("content1")()) + require.NoError(t, err) + + p2, err := api.Unixfs().Add(ctx, strFile("content2")()) + require.NoError(t, err) + + p3, err := api.Unixfs().Add(ctx, strFile("content3")()) + require.NoError(t, err) + + p4, err := api.Unixfs().Add(ctx, strFile("content4")()) + require.NoError(t, err) + + // Test 1: Pin with name + err = api.Pin().Add(ctx, p1, opt.Pin.Name("test-pin-1")) + require.NoError(t, err, "failed to add pin with name") + + // Test 2: Pin without name + err = api.Pin().Add(ctx, p2) + require.NoError(t, err, "failed to add pin without name") + + // Test 3: List pins with detailed option to get names + pins := make(chan iface.Pin) + go func() { + err = api.Pin().Ls(ctx, pins, opt.Pin.Ls.Detailed(true)) + }() + + pinMap := make(map[string]string) + for pin := range pins { + pinMap[pin.Path().String()] = pin.Name() + } + require.NoError(t, err, "failed to list pins with names") + + // Verify pin names + name1, ok := pinMap[p1.String()] + require.True(t, ok, "pin for %s not found", p1) + require.Equal(t, "test-pin-1", name1, "unexpected pin name for %s", p1) + + name2, ok := pinMap[p2.String()] + require.True(t, ok, "pin for %s not found", p2) + require.Empty(t, name2, "expected empty pin name for %s, got '%s'", p2, name2) + + // Test 4: Pin update preserves name + err = api.Pin().Add(ctx, p3, opt.Pin.Name("updatable-pin")) + require.NoError(t, err, "failed to add pin with name for update test") + + err = api.Pin().Update(ctx, p3, p4) + require.NoError(t, err, "failed to update pin") + + // Verify name was preserved after update + pins2 := make(chan iface.Pin) + go func() { + err = api.Pin().Ls(ctx, pins2, opt.Pin.Ls.Detailed(true)) + }() + + updatedPinMap := make(map[string]string) + for pin := range pins2 { + updatedPinMap[pin.Path().String()] = pin.Name() + } + require.NoError(t, err, "failed to list pins after update") + + // Old pin should not exist + _, oldExists := updatedPinMap[p3.String()] + require.False(t, oldExists, "old pin %s should not exist after update", p3) + + // New pin should have the preserved name + name4, ok := updatedPinMap[p4.String()] + require.True(t, ok, "updated pin for %s not found", p4) + require.Equal(t, "updatable-pin", name4, "pin name not preserved after update from %s to %s", p3, p4) + + // Test 5: Re-pinning with different name updates the name + err = api.Pin().Add(ctx, p1, opt.Pin.Name("new-name-for-p1")) + require.NoError(t, err, "failed to re-pin with new name") + + // Verify name was updated + pins3 := make(chan iface.Pin) + go func() { + err = api.Pin().Ls(ctx, pins3, opt.Pin.Ls.Detailed(true)) + }() + + repinMap := make(map[string]string) + for pin := range pins3 { + repinMap[pin.Path().String()] = pin.Name() + } + require.NoError(t, err, "failed to list pins after re-pin") + + rePinnedName, ok := repinMap[p1.String()] + require.True(t, ok, "re-pinned content %s not found", p1) + require.Equal(t, "new-name-for-p1", rePinnedName, "pin name not updated after re-pinning %s", p1) + + // Test 6: Direct pin with name + p5, err := api.Unixfs().Add(ctx, strFile("direct-content")()) + require.NoError(t, err) + + err = api.Pin().Add(ctx, p5, opt.Pin.Recursive(false), opt.Pin.Name("direct-pin-name")) + require.NoError(t, err, "failed to add direct pin with name") + + // Verify direct pin has name + directPins := make(chan iface.Pin) + typeOpt, err := opt.Pin.Ls.Type("direct") + require.NoError(t, err, "failed to create type option") + go func() { + err = api.Pin().Ls(ctx, directPins, typeOpt, opt.Pin.Ls.Detailed(true)) + }() + + directPinMap := make(map[string]string) + for pin := range directPins { + directPinMap[pin.Path().String()] = pin.Name() + } + require.NoError(t, err, "failed to list direct pins") + + directName, ok := directPinMap[p5.String()] + require.True(t, ok, "direct pin %s not found", p5) + require.Equal(t, "direct-pin-name", directName, "unexpected name for direct pin %s", p5) + + // Test 7: List without detailed option doesn't return names + pinsNoDetails := make(chan iface.Pin) + go func() { + err = api.Pin().Ls(ctx, pinsNoDetails) + }() + + noDetailsMap := make(map[string]string) + for pin := range pinsNoDetails { + noDetailsMap[pin.Path().String()] = pin.Name() + } + require.NoError(t, err, "failed to list pins without detailed option") + + // All names should be empty without detailed option + for path, name := range noDetailsMap { + require.Empty(t, name, "expected empty name for %s without detailed option, got '%s'", path, name) + } +} + func assertNotPinned(t *testing.T, ctx context.Context, api iface.CoreAPI, p path.Path) { t.Helper() diff --git a/docs/changelogs/v0.38.md b/docs/changelogs/v0.38.md index 10514970f..440ee0f9d 100644 --- a/docs/changelogs/v0.38.md +++ b/docs/changelogs/v0.38.md @@ -64,6 +64,10 @@ Gateway error pages now provide more actionable information during content retri > - **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. > - **Retry button on all error pages**: Every gateway error page now includes a retry button for quick page refresh without manual URL re-entry. +#### 📌 Pin name improvements + +`ipfs pin ls --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)). + #### 🛠️ Identity CID size enforcement and `ipfs files write` fixes **Identity CID size limits are now enforced** diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index a932ff6c8..78fa7826d 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -7,7 +7,7 @@ go 1.25 replace github.com/ipfs/kubo => ./../../.. require ( - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 github.com/libp2p/go-libp2p v0.43.0 github.com/multiformats/go-multiaddr v0.16.1 @@ -73,10 +73,10 @@ require ( github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.2.2 // indirect + github.com/ipfs/go-block-format v0.2.3 // indirect github.com/ipfs/go-cid v0.5.0 // indirect github.com/ipfs/go-cidutil v0.1.0 // indirect - github.com/ipfs/go-datastore v0.8.4 // indirect + github.com/ipfs/go-datastore v0.9.0 // indirect github.com/ipfs/go-ds-badger v0.3.4 // indirect github.com/ipfs/go-ds-flatfs v0.5.5 // indirect github.com/ipfs/go-ds-leveldb v0.5.2 // indirect @@ -88,14 +88,14 @@ require ( github.com/ipfs/go-ipfs-pq v0.0.3 // indirect github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect github.com/ipfs/go-ipld-cbor v0.2.1 // indirect - github.com/ipfs/go-ipld-format v0.6.2 // indirect + github.com/ipfs/go-ipld-format v0.6.3 // indirect github.com/ipfs/go-ipld-git v0.1.1 // indirect github.com/ipfs/go-ipld-legacy v0.2.2 // indirect github.com/ipfs/go-log/v2 v2.8.1 // indirect github.com/ipfs/go-metrics-interface v0.3.0 // indirect github.com/ipfs/go-peertaskqueue v0.8.2 // indirect github.com/ipfs/go-test v0.2.3 // indirect - github.com/ipfs/go-unixfsnode v1.10.1 // indirect + github.com/ipfs/go-unixfsnode v1.10.2 // indirect github.com/ipld/go-car/v2 v2.15.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect github.com/ipld/go-ipld-prime v0.21.0 // indirect @@ -209,15 +209,16 @@ require ( go.uber.org/zap/exp v0.3.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/net v0.43.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect + golang.org/x/mod v0.28.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index 3bb218f67..bb3e3b153 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -289,13 +289,13 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ= -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8= +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= 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 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc= -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w= +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 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 github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU= -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk= +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y= github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= 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 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA= github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc= github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM= -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY= +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8= +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg= github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24= github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk= 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 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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 golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go.mod b/go.mod index daf41e1b8..a1d466549 100644 --- a/go.mod +++ b/go.mod @@ -22,11 +22,11 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/ipfs-shipyard/nopfs v0.0.14 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 - github.com/ipfs/go-block-format v0.2.2 + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f + github.com/ipfs/go-block-format v0.2.3 github.com/ipfs/go-cid v0.5.0 github.com/ipfs/go-cidutil v0.1.0 - github.com/ipfs/go-datastore v0.8.4 + github.com/ipfs/go-datastore v0.9.0 github.com/ipfs/go-detect-race v0.0.1 github.com/ipfs/go-ds-badger v0.3.4 github.com/ipfs/go-ds-flatfs v0.5.5 @@ -36,14 +36,14 @@ require ( github.com/ipfs/go-fs-lock v0.1.1 github.com/ipfs/go-ipfs-cmds v0.15.0 github.com/ipfs/go-ipld-cbor v0.2.1 - github.com/ipfs/go-ipld-format v0.6.2 + github.com/ipfs/go-ipld-format v0.6.3 github.com/ipfs/go-ipld-git v0.1.1 github.com/ipfs/go-ipld-legacy v0.2.2 github.com/ipfs/go-log/v2 v2.8.1 github.com/ipfs/go-metrics-interface v0.3.0 github.com/ipfs/go-metrics-prometheus v0.1.0 github.com/ipfs/go-test v0.2.3 - github.com/ipfs/go-unixfsnode v1.10.1 + github.com/ipfs/go-unixfsnode v1.10.2 github.com/ipld/go-car/v2 v2.15.0 github.com/ipld/go-codec-dagpb v1.7.0 github.com/ipld/go-ipld-prime v0.21.0 @@ -87,9 +87,9 @@ require ( go.uber.org/dig v1.19.0 go.uber.org/fx v1.24.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.41.0 - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b - golang.org/x/mod v0.27.0 + golang.org/x/crypto v0.42.0 + golang.org/x/exp v0.0.0-20250911091902-df9299821621 + golang.org/x/mod v0.28.0 golang.org/x/sync v0.17.0 golang.org/x/sys v0.36.0 google.golang.org/protobuf v1.36.9 @@ -254,12 +254,13 @@ require ( go.uber.org/zap/exp v0.3.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/net v0.43.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/oauth2 v0.31.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect diff --git a/go.sum b/go.sum index 48837ace1..9bf3c29df 100644 --- a/go.sum +++ b/go.sum @@ -356,13 +356,13 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ= -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8= +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= 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 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc= -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w= +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 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 github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU= -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk= +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y= github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI= 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 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA= github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc= github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM= -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY= +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8= +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg= github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24= github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk= 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 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/test/cli/pin_ls_names_test.go b/test/cli/pin_ls_names_test.go new file mode 100644 index 000000000..54532b6b2 --- /dev/null +++ b/test/cli/pin_ls_names_test.go @@ -0,0 +1,534 @@ +package cli + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/ipfs/kubo/test/cli/harness" + "github.com/stretchr/testify/require" +) + +// pinInfo represents the JSON structure for pin ls output +type pinInfo struct { + Type string `json:"Type"` + Name string `json:"Name"` +} + +// pinLsJSON represents the JSON output structure for pin ls command +type pinLsJSON struct { + Keys map[string]pinInfo `json:"Keys"` +} + +// Helper function to initialize a test node with daemon +func setupTestNode(t *testing.T) *harness.Node { + t.Helper() + node := harness.NewT(t).NewNode().Init() + node.StartDaemon("--offline") + return node +} + +// Helper function to assert pin name and CID are present in output +func assertPinOutput(t *testing.T, output, cid, pinName string) { + t.Helper() + require.Contains(t, output, pinName, "pin name '%s' not found in output: %s", pinName, output) + require.Contains(t, output, cid, "CID %s not found in output: %s", cid, output) +} + +// Helper function to assert CID is present but name is not +func assertCIDOnly(t *testing.T, output, cid string) { + t.Helper() + require.Contains(t, output, cid, "CID %s not found in output: %s", cid, output) +} + +// Helper function to assert neither CID nor name are present +func assertNotPresent(t *testing.T, output, cid, pinName string) { + t.Helper() + require.NotContains(t, output, cid, "CID %s should not be present in output: %s", cid, output) + require.NotContains(t, output, pinName, "pin name '%s' should not be present in output: %s", pinName, output) +} + +// Test that pin ls returns names when querying specific CIDs with --names flag +func TestPinLsWithNamesForSpecificCIDs(t *testing.T) { + t.Parallel() + + t.Run("pin ls with specific CID returns name", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add content without pinning + cidA := node.IPFSAddStr("content A", "--pin=false") + cidB := node.IPFSAddStr("content B", "--pin=false") + cidC := node.IPFSAddStr("content C", "--pin=false") + + // Pin with names + node.IPFS("pin", "add", "--name=pin-a", cidA) + node.IPFS("pin", "add", "--name=pin-b", cidB) + node.IPFS("pin", "add", cidC) // No name + + // Test: pin ls --names should return the name + res := node.IPFS("pin", "ls", cidA, "--names") + assertPinOutput(t, res.Stdout.String(), cidA, "pin-a") + + res = node.IPFS("pin", "ls", cidB, "--names") + assertPinOutput(t, res.Stdout.String(), cidB, "pin-b") + + // Test: pin without name should work + res = node.IPFS("pin", "ls", cidC, "--names") + output := res.Stdout.String() + assertCIDOnly(t, output, cidC) + require.Contains(t, output, "recursive", "pin type 'recursive' not found for CID %s in output: %s", cidC, output) + + // Test: without --names flag, no names returned + res = node.IPFS("pin", "ls", cidA) + output = res.Stdout.String() + require.NotContains(t, output, "pin-a", "pin name 'pin-a' should not be present without --names flag, but found in: %s", output) + assertCIDOnly(t, output, cidA) + }) + + t.Run("pin ls with multiple CIDs returns names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create test content + cidA := node.IPFSAddStr("multi A", "--pin=false") + cidB := node.IPFSAddStr("multi B", "--pin=false") + + // Pin with names + node.IPFS("pin", "add", "--name=multi-pin-a", cidA) + node.IPFS("pin", "add", "--name=multi-pin-b", cidB) + + // Test multiple CIDs at once + res := node.IPFS("pin", "ls", cidA, cidB, "--names") + output := res.Stdout.String() + assertPinOutput(t, output, cidA, "multi-pin-a") + assertPinOutput(t, output, cidB, "multi-pin-b") + }) + + t.Run("pin ls without CID lists all pins with names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create and pin content with names + cidA := node.IPFSAddStr("list all A", "--pin=false") + cidB := node.IPFSAddStr("list all B", "--pin=false") + cidC := node.IPFSAddStr("list all C", "--pin=false") + + node.IPFS("pin", "add", "--name=all-pin-a", cidA) + node.IPFS("pin", "add", "--name=all-pin-b", "--recursive=false", cidB) + node.IPFS("pin", "add", cidC) // No name + + // Test: pin ls --names (without CID) should list all pins with their names + res := node.IPFS("pin", "ls", "--names") + output := res.Stdout.String() + + // Should contain all pins with their names + assertPinOutput(t, output, cidA, "all-pin-a") + assertPinOutput(t, output, cidB, "all-pin-b") + assertCIDOnly(t, output, cidC) + + // Pin C should appear but without a name (just type) + lines := strings.Split(output, "\n") + for _, line := range lines { + if strings.Contains(line, cidC) { + // Should have CID and type but no name + require.Contains(t, line, "recursive", "pin type 'recursive' not found for unnamed pin %s in line: %s", cidC, line) + require.NotContains(t, line, "all-pin", "pin name should not be present for unnamed pin %s, but found in line: %s", cidC, line) + } + } + }) + + t.Run("pin ls --type with --names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create test content + cidDirect := node.IPFSAddStr("direct content", "--pin=false") + cidRecursive := node.IPFSAddStr("recursive content", "--pin=false") + + // Create a DAG for indirect testing + childCid := node.IPFSAddStr("child for indirect", "--pin=false") + parentContent := fmt.Sprintf(`{"link": "/ipfs/%s"}`, childCid) + parentCid := node.PipeStrToIPFS(parentContent, "dag", "put", "--input-codec=json", "--store-codec=dag-cbor").Stdout.Trimmed() + + // Pin with different types and names + node.IPFS("pin", "add", "--name=direct-pin", "--recursive=false", cidDirect) + node.IPFS("pin", "add", "--name=recursive-pin", cidRecursive) + node.IPFS("pin", "add", "--name=parent-pin", parentCid) + + // Test: --type=direct --names + res := node.IPFS("pin", "ls", "--type=direct", "--names") + output := res.Stdout.String() + assertPinOutput(t, output, cidDirect, "direct-pin") + assertNotPresent(t, output, cidRecursive, "recursive-pin") + + // Test: --type=recursive --names + res = node.IPFS("pin", "ls", "--type=recursive", "--names") + output = res.Stdout.String() + assertPinOutput(t, output, cidRecursive, "recursive-pin") + assertPinOutput(t, output, parentCid, "parent-pin") + assertNotPresent(t, output, cidDirect, "direct-pin") + + // Test: --type=indirect with proper directory structure + // Create a directory with a file for indirect pin testing + dirPath := t.TempDir() + require.NoError(t, os.WriteFile(filepath.Join(dirPath, "file.txt"), []byte("test content"), 0644)) + + // Add directory recursively + dirAddRes := node.IPFS("add", "-r", "-q", dirPath) + dirCidStr := strings.TrimSpace(dirAddRes.Stdout.Lines()[len(dirAddRes.Stdout.Lines())-1]) + + // Add file separately without pinning to get its CID + fileAddRes := node.IPFS("add", "-q", "--pin=false", filepath.Join(dirPath, "file.txt")) + fileCidStr := strings.TrimSpace(fileAddRes.Stdout.String()) + + // Check if file shows as indirect + res = node.IPFS("pin", "ls", "--type=indirect", fileCidStr) + output = res.Stdout.String() + require.Contains(t, output, fileCidStr, "indirect pin CID %s not found in output: %s", fileCidStr, output) + require.Contains(t, output, "indirect through "+dirCidStr, "indirect relationship not found for CID %s through %s in output: %s", fileCidStr, dirCidStr, output) + + // Test: --type=all --names + res = node.IPFS("pin", "ls", "--type=all", "--names") + output = res.Stdout.String() + assertPinOutput(t, output, cidDirect, "direct-pin") + assertPinOutput(t, output, cidRecursive, "recursive-pin") + assertPinOutput(t, output, parentCid, "parent-pin") + // Indirect pins are included in --type=all output + }) + + t.Run("pin ls JSON output with names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add and pin content with name + cidA := node.IPFSAddStr("json content", "--pin=false") + node.IPFS("pin", "add", "--name=json-pin", cidA) + + // Test JSON output with specific CID + res := node.IPFS("pin", "ls", cidA, "--names", "--enc=json") + var pinOutput pinLsJSON + err := json.Unmarshal([]byte(res.Stdout.String()), &pinOutput) + require.NoError(t, err, "failed to unmarshal JSON output: %s", res.Stdout.String()) + + pinData, ok := pinOutput.Keys[cidA] + require.True(t, ok, "CID %s should be in Keys map, got: %+v", cidA, pinOutput.Keys) + require.Equal(t, "recursive", pinData.Type, "expected pin type 'recursive', got '%s'", pinData.Type) + require.Equal(t, "json-pin", pinData.Name, "expected pin name 'json-pin', got '%s'", pinData.Name) + + // Without names flag + res = node.IPFS("pin", "ls", cidA, "--enc=json") + err = json.Unmarshal([]byte(res.Stdout.String()), &pinOutput) + require.NoError(t, err, "failed to unmarshal JSON output: %s", res.Stdout.String()) + + pinData, ok = pinOutput.Keys[cidA] + require.True(t, ok, "CID %s should be in Keys map, got: %+v", cidA, pinOutput.Keys) + // Name should be empty without --names flag + require.Equal(t, "", pinData.Name, "pin name should be empty without --names flag, got '%s'", pinData.Name) + + // Test JSON output without CID (list all) + res = node.IPFS("pin", "ls", "--names", "--enc=json") + var listOutput pinLsJSON + err = json.Unmarshal([]byte(res.Stdout.String()), &listOutput) + require.NoError(t, err, "failed to unmarshal JSON list output: %s", res.Stdout.String()) + // Should have at least one pin (the one we just added) + require.NotEmpty(t, listOutput.Keys, "pin list should not be empty") + // Check that our pin is in the list + pinData, ok = listOutput.Keys[cidA] + require.True(t, ok, "our pin with CID %s should be in the list, got: %+v", cidA, listOutput.Keys) + require.Equal(t, "json-pin", pinData.Name, "expected pin name 'json-pin' in list, got '%s'", pinData.Name) + }) + + t.Run("direct and indirect pins with names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create a small DAG: parent -> child + childCid := node.IPFSAddStr("child content", "--pin=false") + + // Create parent that references child + parentContent := fmt.Sprintf(`{"link": "/ipfs/%s"}`, childCid) + parentCid := node.PipeStrToIPFS(parentContent, "dag", "put", "--input-codec=json", "--store-codec=dag-cbor").Stdout.Trimmed() + + // Pin child directly with a name + node.IPFS("pin", "add", "--name=direct-child", "--recursive=false", childCid) + + // Pin parent recursively with a name + node.IPFS("pin", "add", "--name=recursive-parent", parentCid) + + // Check direct pin with specific CID + res := node.IPFS("pin", "ls", "--type=direct", childCid, "--names") + output := res.Stdout.String() + require.Contains(t, output, "direct-child", "pin name 'direct-child' not found in output: %s", output) + require.Contains(t, output, "direct", "pin type 'direct' not found in output: %s", output) + + // Check recursive pin with specific CID + res = node.IPFS("pin", "ls", "--type=recursive", parentCid, "--names") + output = res.Stdout.String() + require.Contains(t, output, "recursive-parent", "pin name 'recursive-parent' not found in output: %s", output) + require.Contains(t, output, "recursive", "pin type 'recursive' not found in output: %s", output) + + // Child is both directly pinned and indirectly pinned through parent + // Both relationships are valid and can be checked + }) + + t.Run("pin update preserves name", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create two pieces of content + cidOld := node.IPFSAddStr("old content", "--pin=false") + cidNew := node.IPFSAddStr("new content", "--pin=false") + + // Pin with name + node.IPFS("pin", "add", "--name=my-pin", cidOld) + + // Update pin + node.IPFS("pin", "update", cidOld, cidNew) + + // Check that new pin has the same name + res := node.IPFS("pin", "ls", cidNew, "--names") + require.Contains(t, res.Stdout.String(), "my-pin", "pin name 'my-pin' not preserved after update, output: %s", res.Stdout.String()) + + // Old pin should not exist + res = node.RunIPFS("pin", "ls", cidOld) + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for unpinned CID, got %d", res.ExitCode()) + require.Contains(t, res.Stderr.String(), "is not pinned", "expected 'is not pinned' error for old CID %s, got: %s", cidOld, res.Stderr.String()) + }) + + t.Run("pin ls with invalid CID returns error", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init() + + res := node.RunIPFS("pin", "ls", "invalid-cid") + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for invalid CID, got %d", res.ExitCode()) + require.Contains(t, res.Stderr.String(), "invalid", "expected 'invalid' in error message, got: %s", res.Stderr.String()) + }) + + t.Run("pin ls with unpinned CID returns error", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add content without pinning + cid := node.IPFSAddStr("unpinned content", "--pin=false") + + res := node.RunIPFS("pin", "ls", cid) + require.Equal(t, 1, res.ExitCode(), "expected exit code 1 for unpinned CID, got %d", res.ExitCode()) + require.Contains(t, res.Stderr.String(), "is not pinned", "expected 'is not pinned' error for CID %s, got: %s", cid, res.Stderr.String()) + }) + + t.Run("pin with special characters in name", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + testCases := []struct { + name string + pinName string + }{ + {"unicode", "test-📌-pin"}, + {"spaces", "test pin name"}, + {"special chars", "test!@#$%"}, + {"path-like", "test/pin/name"}, + {"dots", "test.pin.name"}, + {"long name", strings.Repeat("a", 255)}, + {"empty name", ""}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cid := node.IPFSAddStr("content for "+tc.name, "--pin=false") + node.IPFS("pin", "add", "--name="+tc.pinName, cid) + + res := node.IPFS("pin", "ls", cid, "--names") + if tc.pinName != "" { + require.Contains(t, res.Stdout.String(), tc.pinName, + "pin name '%s' not found in output for test case '%s'", tc.pinName, tc.name) + } + }) + } + }) + + t.Run("concurrent pin operations with names", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Create multiple goroutines adding pins with names + numPins := 10 + done := make(chan struct{}, numPins) + + for i := 0; i < numPins; i++ { + go func(idx int) { + defer func() { done <- struct{}{} }() + + content := fmt.Sprintf("concurrent content %d", idx) + cid := node.IPFSAddStr(content, "--pin=false") + pinName := fmt.Sprintf("concurrent-pin-%d", idx) + node.IPFS("pin", "add", "--name="+pinName, cid) + }(i) + } + + // Wait for all goroutines + for i := 0; i < numPins; i++ { + <-done + } + + // Verify all pins have correct names + res := node.IPFS("pin", "ls", "--names") + output := res.Stdout.String() + for i := 0; i < numPins; i++ { + pinName := fmt.Sprintf("concurrent-pin-%d", i) + require.Contains(t, output, pinName, + "concurrent pin name '%s' not found in output", pinName) + } + }) + + t.Run("pin rm removes name association", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add and pin with name + cid := node.IPFSAddStr("content to remove", "--pin=false") + node.IPFS("pin", "add", "--name=to-be-removed", cid) + + // Verify pin exists with name + res := node.IPFS("pin", "ls", cid, "--names") + require.Contains(t, res.Stdout.String(), "to-be-removed") + + // Remove pin + node.IPFS("pin", "rm", cid) + + // Verify pin and name are gone + res = node.RunIPFS("pin", "ls", cid) + require.Equal(t, 1, res.ExitCode()) + require.Contains(t, res.Stderr.String(), "is not pinned") + }) + + t.Run("garbage collection preserves named pins", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add content with and without pin names + cidNamed := node.IPFSAddStr("named content", "--pin=false") + cidUnnamed := node.IPFSAddStr("unnamed content", "--pin=false") + cidUnpinned := node.IPFSAddStr("unpinned content", "--pin=false") + + node.IPFS("pin", "add", "--name=important-data", cidNamed) + node.IPFS("pin", "add", cidUnnamed) + + // Run garbage collection + node.IPFS("repo", "gc") + + // Named and unnamed pins should still exist + res := node.IPFS("pin", "ls", cidNamed, "--names") + require.Contains(t, res.Stdout.String(), "important-data") + + res = node.IPFS("pin", "ls", cidUnnamed) + require.Contains(t, res.Stdout.String(), cidUnnamed) + + // Unpinned content should be gone (cat should fail) + res = node.RunIPFS("cat", cidUnpinned) + require.NotEqual(t, 0, res.ExitCode(), "unpinned content should be garbage collected") + }) + + t.Run("pin add with same name can be used for multiple pins", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + + // Add two different pieces of content + cid1 := node.IPFSAddStr("first content", "--pin=false") + cid2 := node.IPFSAddStr("second content", "--pin=false") + + // Pin both with the same name - this is allowed + node.IPFS("pin", "add", "--name=shared-name", cid1) + node.IPFS("pin", "add", "--name=shared-name", cid2) + + // List all pins with names + res := node.IPFS("pin", "ls", "--names") + output := res.Stdout.String() + + // Both CIDs should be pinned + require.Contains(t, output, cid1) + require.Contains(t, output, cid2) + + // Both pins can have the same name + lines := strings.Split(output, "\n") + foundCid1WithName := false + foundCid2WithName := false + for _, line := range lines { + if strings.Contains(line, cid1) && strings.Contains(line, "shared-name") { + foundCid1WithName = true + } + if strings.Contains(line, cid2) && strings.Contains(line, "shared-name") { + foundCid2WithName = true + } + } + require.True(t, foundCid1WithName, "first pin should have the name") + require.True(t, foundCid2WithName, "second pin should have the name") + }) + + t.Run("pin names persist across daemon restarts", func(t *testing.T) { + t.Parallel() + node := harness.NewT(t).NewNode().Init() + node.StartDaemon("--offline") + + // Add content with pin name + cid := node.IPFSAddStr("persistent content") + node.IPFS("pin", "add", "--name=persistent-pin", cid) + + // Restart daemon + node.StopDaemon() + node.StartDaemon("--offline") + + // Check pin name persisted + res := node.IPFS("pin", "ls", cid, "--names") + require.Contains(t, res.Stdout.String(), "persistent-pin", + "pin name should persist across daemon restarts") + + node.StopDaemon() + }) +} + +// TestPinLsEdgeCases tests edge cases for pin ls command +func TestPinLsEdgeCases(t *testing.T) { + t.Parallel() + + t.Run("invalid pin type returns error", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + defer node.StopDaemon() + + // Try to list pins with invalid type + res := node.RunIPFS("pin", "ls", "--type=invalid") + require.NotEqual(t, 0, res.ExitCode()) + require.Contains(t, res.Stderr.String(), "invalid type 'invalid'") + require.Contains(t, res.Stderr.String(), "must be one of {direct, indirect, recursive, all}") + }) + + t.Run("non-existent path returns proper error", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + defer node.StopDaemon() + + // Try to list a non-existent CID + fakeCID := "QmNonExistent123456789" + res := node.RunIPFS("pin", "ls", fakeCID) + require.NotEqual(t, 0, res.ExitCode()) + }) + + t.Run("unpinned CID returns not pinned error", func(t *testing.T) { + t.Parallel() + node := setupTestNode(t) + defer node.StopDaemon() + + // Add content but don't pin it explicitly (it's just in blockstore) + unpinnedCID := node.IPFSAddStr("unpinned content", "--pin=false") + + // Try to list specific unpinned CID + res := node.RunIPFS("pin", "ls", unpinnedCID) + require.NotEqual(t, 0, res.ExitCode()) + require.Contains(t, res.Stderr.String(), "is not pinned") + }) +} diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index e18d430bc..e31258307 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -135,18 +135,18 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 // indirect + github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f // indirect github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-block-format v0.2.2 // indirect + github.com/ipfs/go-block-format v0.2.3 // indirect github.com/ipfs/go-cid v0.5.0 // indirect - github.com/ipfs/go-datastore v0.8.4 // indirect + github.com/ipfs/go-datastore v0.9.0 // indirect github.com/ipfs/go-dsqueue v0.0.5 // indirect github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect github.com/ipfs/go-ipld-cbor v0.2.1 // indirect - github.com/ipfs/go-ipld-format v0.6.2 // indirect + github.com/ipfs/go-ipld-format v0.6.3 // indirect github.com/ipfs/go-ipld-legacy v0.2.2 // indirect github.com/ipfs/go-metrics-interface v0.3.0 // indirect - github.com/ipfs/go-unixfsnode v1.10.1 // indirect + github.com/ipfs/go-unixfsnode v1.10.2 // indirect github.com/ipfs/kubo v0.31.0 // indirect github.com/ipld/go-car/v2 v2.15.0 // indirect github.com/ipld/go-codec-dagpb v1.7.0 // indirect @@ -327,17 +327,17 @@ require ( go.uber.org/zap v1.27.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.27.0 // indirect - golang.org/x/net v0.43.0 // indirect + golang.org/x/mod v0.28.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/protobuf v1.36.9 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 26b85c674..b15c30b03 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -332,18 +332,18 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs= -github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f h1:In4WBnF9sysZwHV6bYTdnLtyRMOQTtvW1leZzxP4bbg= +github.com/ipfs/boxo v0.34.1-0.20250919000230-031df82b284f/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= -github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ= -github.com/ipfs/go-block-format v0.2.2/go.mod h1:vmuefuWU6b+9kIU0vZJgpiJt1yicQz9baHXE8qR+KB8= +github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= +github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q= github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= -github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc= -github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= +github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w= +github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 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 github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw= github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= -github.com/ipfs/go-ipld-format v0.6.2 h1:bPZQ+A05ol0b3lsJSl0bLvwbuQ+HQbSsdGTy4xtYUkU= -github.com/ipfs/go-ipld-format v0.6.2/go.mod h1:nni2xFdHKx5lxvXJ6brt/pndtGxKAE+FPR1rg4jTkyk= +github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= +github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ= github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU= github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= @@ -374,8 +374,8 @@ github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8 github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA= github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc= github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= -github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM= -github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY= +github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8= +github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg= github.com/ipfs/hang-fds v0.1.0 h1:deBiFlWHsVGzJ0ZMaqscEqRM1r2O1rFZ59UiQXb1Xko= github.com/ipfs/hang-fds v0.1.0/go.mod h1:29VLWOn3ftAgNNgXg/al7b11UzuQ+w7AwtCGcTaWkbM= 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 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 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= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=