diff --git a/.dockerignore b/.dockerignore index 7f6bbbfe9..10dd5fd88 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,3 +5,9 @@ Dockerfile.fast !.git/refs/ !.git/packed-refs test/sharness/lib/sharness/ + +# The Docker client might not be running on Linux +# so delete any compiled binaries +bin/gx +bin/gx* +bin/tmp diff --git a/assets/assets.go b/assets/assets.go index 923d83a42..bcb781618 100644 --- a/assets/assets.go +++ b/assets/assets.go @@ -12,7 +12,7 @@ import ( "github.com/ipfs/go-ipfs/core" "github.com/ipfs/go-ipfs/core/coreunix" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" // this import keeps gx from thinking the dep isn't used _ "gx/ipfs/QmdZ4PvPHFQVLLEve7DgoKDcSY19wwpGBB1GKjjKi2rEL1/dir-index-html" diff --git a/blocks/blockstoreutil/remove.go b/blocks/blockstoreutil/remove.go index 70e02d7d7..f4ae8733b 100644 --- a/blocks/blockstoreutil/remove.go +++ b/blocks/blockstoreutil/remove.go @@ -8,8 +8,8 @@ import ( "github.com/ipfs/go-ipfs/pin" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - bs "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + bs "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) // RemovedBlock is used to respresent the result of removing a block. diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 01c111935..afcef28f3 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -412,22 +412,32 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error return nil, fmt.Errorf("serveHTTPApi: GetConfig() failed: %s", err) } + apiAddrs := make([]string, 0, 2) apiAddr, _ := req.Options[commands.ApiOption].(string) if apiAddr == "" { - apiAddr = cfg.Addresses.API - } - apiMaddr, err := ma.NewMultiaddr(apiAddr) - if err != nil { - return nil, fmt.Errorf("serveHTTPApi: invalid API address: %q (err: %s)", apiAddr, err) + apiAddrs = cfg.Addresses.API + } else { + apiAddrs = append(apiAddrs, apiAddr) } - apiLis, err := manet.Listen(apiMaddr) - if err != nil { - return nil, fmt.Errorf("serveHTTPApi: manet.Listen(%s) failed: %s", apiMaddr, err) + listeners := make([]manet.Listener, 0, len(apiAddrs)) + for _, addr := range apiAddrs { + apiMaddr, err := ma.NewMultiaddr(addr) + if err != nil { + return nil, fmt.Errorf("serveHTTPApi: invalid API address: %q (err: %s)", apiAddr, err) + } + + apiLis, err := manet.Listen(apiMaddr) + if err != nil { + return nil, fmt.Errorf("serveHTTPApi: manet.Listen(%s) failed: %s", apiMaddr, err) + } + + // we might have listened to /tcp/0 - lets see what we are listing on + apiMaddr = apiLis.Multiaddr() + fmt.Printf("API server listening on %s\n", apiMaddr) + + listeners = append(listeners, apiLis) } - // we might have listened to /tcp/0 - lets see what we are listing on - apiMaddr = apiLis.Multiaddr() - fmt.Printf("API server listening on %s\n", apiMaddr) // by default, we don't let you load arbitrary ipfs objects through the api, // because this would open up the api to scripting vulnerabilities. @@ -462,15 +472,25 @@ func serveHTTPApi(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, error return nil, fmt.Errorf("serveHTTPApi: ConstructNode() failed: %s", err) } - if err := node.Repo.SetAPIAddr(apiMaddr); err != nil { + if err := node.Repo.SetAPIAddr(listeners[0].Multiaddr()); err != nil { return nil, fmt.Errorf("serveHTTPApi: SetAPIAddr() failed: %s", err) } errc := make(chan error) + var wg sync.WaitGroup + for _, apiLis := range listeners { + wg.Add(1) + go func(lis manet.Listener) { + defer wg.Done() + errc <- corehttp.Serve(node, manet.NetListener(lis), opts...) + }(apiLis) + } + go func() { - errc <- corehttp.Serve(node, manet.NetListener(apiLis), opts...) + wg.Wait() close(errc) }() + return errc, nil } @@ -512,27 +532,33 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e return nil, fmt.Errorf("serveHTTPGateway: GetConfig() failed: %s", err) } - gatewayMaddr, err := ma.NewMultiaddr(cfg.Addresses.Gateway) - if err != nil { - return nil, fmt.Errorf("serveHTTPGateway: invalid gateway address: %q (err: %s)", cfg.Addresses.Gateway, err) - } - writable, writableOptionFound := req.Options[writableKwd].(bool) if !writableOptionFound { writable = cfg.Gateway.Writable } - gwLis, err := manet.Listen(gatewayMaddr) - if err != nil { - return nil, fmt.Errorf("serveHTTPGateway: manet.Listen(%s) failed: %s", gatewayMaddr, err) - } - // we might have listened to /tcp/0 - lets see what we are listing on - gatewayMaddr = gwLis.Multiaddr() + gatewayAddrs := cfg.Addresses.Gateway + listeners := make([]manet.Listener, 0, len(gatewayAddrs)) + for _, addr := range gatewayAddrs { + gatewayMaddr, err := ma.NewMultiaddr(addr) + if err != nil { + return nil, fmt.Errorf("serveHTTPGateway: invalid gateway address: %q (err: %s)", addr, err) + } - if writable { - fmt.Printf("Gateway (writable) server listening on %s\n", gatewayMaddr) - } else { - fmt.Printf("Gateway (readonly) server listening on %s\n", gatewayMaddr) + gwLis, err := manet.Listen(gatewayMaddr) + if err != nil { + return nil, fmt.Errorf("serveHTTPGateway: manet.Listen(%s) failed: %s", gatewayMaddr, err) + } + // we might have listened to /tcp/0 - lets see what we are listing on + gatewayMaddr = gwLis.Multiaddr() + + if writable { + fmt.Printf("Gateway (writable) server listening on %s\n", gatewayMaddr) + } else { + fmt.Printf("Gateway (readonly) server listening on %s\n", gatewayMaddr) + } + + listeners = append(listeners, gwLis) } var opts = []corehttp.ServeOption{ @@ -554,10 +580,20 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e } errc := make(chan error) + var wg sync.WaitGroup + for _, lis := range listeners { + wg.Add(1) + go func(lis manet.Listener) { + defer wg.Done() + errc <- corehttp.Serve(node, manet.NetListener(lis), opts...) + }(lis) + } + go func() { - errc <- corehttp.Serve(node, manet.NetListener(gwLis), opts...) + wg.Wait() close(errc) }() + return errc, nil } diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 34364b90e..87b4aed71 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -17,7 +17,7 @@ import ( fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ) diff --git a/cmd/ipfs/ipfs.go b/cmd/ipfs/ipfs.go index 0342007a1..8e74139b0 100644 --- a/cmd/ipfs/ipfs.go +++ b/cmd/ipfs/ipfs.go @@ -92,4 +92,5 @@ var cmdDetailsMap = map[string]cmdDetails{ "diag/cmds": {cannotRunOnClient: true}, "repo/fsck": {cannotRunOnDaemon: true}, "config/edit": {cannotRunOnDaemon: true, doesNotUseRepo: true}, + "cid": {doesNotUseRepo: true}, } diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 9b97caad9..98571908e 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -26,8 +26,8 @@ import ( loggables "gx/ipfs/QmNLzS18jsmwTxXewTm3YnZVLftWCeegNZEBFjMrnvnBrH/go-libp2p-loggables" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" + "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" manet "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net" - "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds/cli" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds/http" diff --git a/cmd/ipfswatch/main.go b/cmd/ipfswatch/main.go index 5c8643703..9e706cc5a 100644 --- a/cmd/ipfswatch/main.go +++ b/cmd/ipfswatch/main.go @@ -16,7 +16,7 @@ import ( fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" process "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" homedir "gx/ipfs/QmdcULN1WCzgoQmcCaUAmEhwcxHYsDrbZ2LvRJKCL8dMrK/go-homedir" fsnotify "gx/ipfs/QmfNjggF4Pt6erqg3NDafD3MdvDHk1qqCVr8pL5hnPucS8/fsnotify" ) diff --git a/cmd/seccat/seccat.go b/cmd/seccat/seccat.go index 5fc265c4d..2a74ae5c5 100644 --- a/cmd/seccat/seccat.go +++ b/cmd/seccat/seccat.go @@ -19,12 +19,12 @@ import ( "os/signal" "syscall" - secio "gx/ipfs/QmPJ6U14u5D2abGVkF3dopCeM1JqigVTUJ7jbAHjTnGZrt/go-libp2p-secio" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + pstoremem "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore/pstoremem" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" + secio "gx/ipfs/QmZSHe9kqEcqUG6DSBrKYULk8EeZLDd1skpHNoSaK6rW4M/go-libp2p-secio" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" - pstoremem "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore/pstoremem" ) var verbose = false diff --git a/commands/request.go b/commands/request.go index 765b81bb5..4197dbaf2 100644 --- a/commands/request.go +++ b/commands/request.go @@ -12,7 +12,7 @@ import ( "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ) diff --git a/core/bootstrap.go b/core/bootstrap.go index b89982745..ff4b27b8d 100644 --- a/core/bootstrap.go +++ b/core/bootstrap.go @@ -12,14 +12,14 @@ import ( math2 "github.com/ipfs/go-ipfs/thirdparty/math2" lgbl "gx/ipfs/QmNLzS18jsmwTxXewTm3YnZVLftWCeegNZEBFjMrnvnBrH/go-libp2p-loggables" + host "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" procctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context" periodicproc "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/periodic" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + inet "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - host "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" - inet "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" ) // ErrNotEnoughBootstrapPeers signals that we do not have enough bootstrap diff --git a/core/bootstrap_test.go b/core/bootstrap_test.go index 88d0530e4..775ee31e8 100644 --- a/core/bootstrap_test.go +++ b/core/bootstrap_test.go @@ -5,8 +5,8 @@ import ( "testing" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ) func TestSubsetWhenMaxIsGreaterThanLengthOfSlice(t *testing.T) { diff --git a/core/builder.go b/core/builder.go index ff39db7fa..29e6e0edd 100644 --- a/core/builder.go +++ b/core/builder.go @@ -14,27 +14,27 @@ import ( repo "github.com/ipfs/go-ipfs/repo" cidv0v1 "github.com/ipfs/go-ipfs/thirdparty/cidv0v1" "github.com/ipfs/go-ipfs/thirdparty/verifbs" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + resolver "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path/resolver" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" + p2phost "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" goprocessctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context" record "gx/ipfs/QmSb4B8ZAAj5ALe9LjfzPyF8Ma6ezC1NTnDF2JQPUJxEXb/go-libp2p-record" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - retry "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/retrystore" - dsync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - cfg "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - libp2p "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + cfg "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + libp2p "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + pstoremem "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore/pstoremem" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + retry "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/retrystore" + dsync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" - p2phost "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" metrics "gx/ipfs/QmekzFM3hPZjTjUFGTABdQkEnQ3PTiMstY198PwSFr5w1Q/go-metrics-interface" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" - pstoremem "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore/pstoremem" ) type BuildCfg struct { diff --git a/core/commands/active.go b/core/commands/active.go index 83f6b0807..e9a9b47e0 100644 --- a/core/commands/active.go +++ b/core/commands/active.go @@ -14,6 +14,10 @@ import ( "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" ) +const ( + verboseOptionName = "v" +) + var ActiveReqsCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List commands run on this IPFS node.", @@ -25,7 +29,7 @@ Lists running and recently run commands. res.SetOutput(req.InvocContext().ReqLog.Report()) }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption("verbose", verboseOptionName, "Print extra information."), }, Subcommands: map[string]*cmds.Command{ "clear": clearInactiveCmd, @@ -44,7 +48,7 @@ Lists running and recently run commands. } buf := new(bytes.Buffer) - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(verboseOptionName).Bool() w := tabwriter.NewWriter(buf, 4, 4, 2, ' ', 0) if verbose { diff --git a/core/commands/add.go b/core/commands/add.go index b7f3d6a84..05484e9ec 100644 --- a/core/commands/add.go +++ b/core/commands/add.go @@ -6,24 +6,15 @@ import ( "os" "strings" - core "github.com/ipfs/go-ipfs/core" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" - "github.com/ipfs/go-ipfs/core/coreunix" - filestore "github.com/ipfs/go-ipfs/filestore" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - dagtest "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag/test" - blockservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" pb "gx/ipfs/QmPtj12fdwuAqj9sBSTNUxBNu8kCGNp8b3o8yUzMm5GHpq/pb" - cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) // ErrDepthLimitExceeded indicates that the max depth has been exceeded. @@ -148,23 +139,11 @@ You can now check what blocks have been created by: return nil }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - cfg, err := n.Repo.Config() - if err != nil { - return err - } - // check if repo will exceed storage limit if added - // TODO: this doesn't handle the case if the hashed file is already in blocks (deduplicated) - // TODO: conditional GC is disabled due to it is somehow not possible to pass the size to the daemon - //if err := corerepo.ConditionalGC(req.Context(), n, uint64(size)); err != nil { - // res.SetError(err, cmdkit.ErrNormal) - // return - //} - progress, _ := req.Options[progressOptionName].(bool) trickle, _ := req.Options[trickleOptionName].(bool) wrap, _ := req.Options[wrapOptionName].(bool) @@ -181,161 +160,59 @@ You can now check what blocks have been created by: inline, _ := req.Options[inlineOptionName].(bool) inlineLimit, _ := req.Options[inlineLimitOptionName].(int) pathName, _ := req.Options[stdinPathName].(string) - - // The arguments are subject to the following constraints. - // - // nocopy -> filestoreEnabled - // nocopy -> rawblocks - // (hash != sha2-256) -> cidv1 - - // NOTE: 'rawblocks -> cidv1' is missing. Legacy reasons. - - // nocopy -> filestoreEnabled - if nocopy && !cfg.Experimental.FilestoreEnabled { - return cmdkit.Errorf(cmdkit.ErrClient, filestore.ErrFilestoreNotEnabled.Error()) - } - - // nocopy -> rawblocks - if nocopy && !rawblks { - // fixed? - if rbset { - return fmt.Errorf("nocopy option requires '--raw-leaves' to be enabled as well") - } - // No, satisfy mandatory constraint. - rawblks = true - } - - // (hash != "sha2-256") -> CIDv1 - if hashFunStr != "sha2-256" && cidVer == 0 { - if cidVerSet { - return cmdkit.Errorf(cmdkit.ErrClient, "CIDv0 only supports sha2-256") - } - cidVer = 1 - } - - // cidV1 -> raw blocks (by default) - if cidVer > 0 && !rbset { - rawblks = true - } - - prefix, err := dag.PrefixForCidVersion(cidVer) - if err != nil { - return err - } + local, _ := req.Options["local"].(bool) hashFunCode, ok := mh.Names[strings.ToLower(hashFunStr)] if !ok { return fmt.Errorf("unrecognized hash function: %s", strings.ToLower(hashFunStr)) } - prefix.MhType = hashFunCode - prefix.MhLength = -1 + events := make(chan interface{}, adderOutChanSize) - if hash { - nilnode, err := core.NewNode(n.Context(), &core.BuildCfg{ - //TODO: need this to be true or all files - // hashed will be stored in memory! - NilRepo: true, - }) - if err != nil { - return err - } - n = nilnode + opts := []options.UnixfsAddOption{ + options.Unixfs.Hash(hashFunCode), + + options.Unixfs.Inline(inline), + options.Unixfs.InlineLimit(inlineLimit), + + options.Unixfs.Chunker(chunker), + + options.Unixfs.Pin(dopin), + options.Unixfs.HashOnly(hash), + options.Unixfs.Local(local), + options.Unixfs.FsCache(fscache), + options.Unixfs.Nocopy(nocopy), + + options.Unixfs.Wrap(wrap), + options.Unixfs.Hidden(hidden), + options.Unixfs.StdinName(pathName), + + options.Unixfs.Progress(progress), + options.Unixfs.Silent(silent), + options.Unixfs.Events(events), } - addblockstore := n.Blockstore - if !(fscache || nocopy) { - addblockstore = bstore.NewGCBlockstore(n.BaseBlocks, n.GCLocker) + if cidVerSet { + opts = append(opts, options.Unixfs.CidVersion(cidVer)) } - exch := n.Exchange - local, _ := req.Options["local"].(bool) - if local { - exch = offline.Exchange(addblockstore) + if rbset { + opts = append(opts, options.Unixfs.RawLeaves(rawblks)) } - bserv := blockservice.New(addblockstore, exch) // hash security 001 - dserv := dag.NewDAGService(bserv) - - outChan := make(chan interface{}, adderOutChanSize) - - fileAdder, err := coreunix.NewAdder(req.Context, n.Pinning, n.Blockstore, dserv) - if err != nil { - return err - } - - fileAdder.Out = outChan - fileAdder.Chunker = chunker - fileAdder.Progress = progress - fileAdder.Hidden = hidden - fileAdder.Trickle = trickle - fileAdder.Wrap = wrap - fileAdder.Pin = dopin - fileAdder.Silent = silent - fileAdder.RawLeaves = rawblks - fileAdder.NoCopy = nocopy - fileAdder.Name = pathName - fileAdder.CidBuilder = prefix - - if inline { - fileAdder.CidBuilder = cidutil.InlineBuilder{ - Builder: fileAdder.CidBuilder, - Limit: inlineLimit, - } - } - - if hash { - md := dagtest.Mock() - emptyDirNode := ft.EmptyDirNode() - // Use the same prefix for the "empty" MFS root as for the file adder. - emptyDirNode.SetCidBuilder(fileAdder.CidBuilder) - mr, err := mfs.NewRoot(req.Context, md, emptyDirNode, nil) - if err != nil { - return err - } - - fileAdder.SetMfsRoot(mr) - } - - addAllAndPin := func(f files.File) error { - // Iterate over each top-level file and add individually. Otherwise the - // single files.File f is treated as a directory, affecting hidden file - // semantics. - for { - file, err := f.NextFile() - if err == io.EOF { - // Finished the list of files. - break - } else if err != nil { - return err - } - if err := fileAdder.AddFile(file); err != nil { - return err - } - } - - // copy intermediary nodes from editor to our actual dagservice - _, err := fileAdder.Finalize() - if err != nil { - return err - } - - if hash { - return nil - } - - return fileAdder.PinRoot() + if trickle { + opts = append(opts, options.Unixfs.Layout(options.TrickleLayout)) } errCh := make(chan error) go func() { var err error defer func() { errCh <- err }() - defer close(outChan) - err = addAllAndPin(req.Files) + defer close(events) + _, err = api.Unixfs().Add(req.Context, req.Files, opts...) }() - err = res.Emit(outChan) + err = res.Emit(events) if err != nil { return err } @@ -401,7 +278,7 @@ You can now check what blocks have been created by: break LOOP } - output := out.(*coreunix.AddedObject) + output := out.(*coreiface.AddEvent) if len(output.Hash) > 0 { lastHash = output.Hash if quieter { @@ -481,5 +358,5 @@ You can now check what blocks have been created by: } }, }, - Type: coreunix.AddedObject{}, + Type: coreiface.AddEvent{}, } diff --git a/core/commands/bitswap.go b/core/commands/bitswap.go index 336b933d6..4959ea606 100644 --- a/core/commands/bitswap.go +++ b/core/commands/bitswap.go @@ -9,8 +9,8 @@ import ( lgc "github.com/ipfs/go-ipfs/commands/legacy" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" e "github.com/ipfs/go-ipfs/core/commands/e" - bitswap "gx/ipfs/QmUdtRsAr9RYxqNwUzeHDhv5bnVppiHLixP1SU4YysVj2S/go-bitswap" - decision "gx/ipfs/QmUdtRsAr9RYxqNwUzeHDhv5bnVppiHLixP1SU4YysVj2S/go-bitswap/decision" + bitswap "gx/ipfs/QmQHbKeMWRNT8koMhh2DrTXZWepYVoGPNXni6JG1L3BhGq/go-bitswap" + decision "gx/ipfs/QmQHbKeMWRNT8koMhh2DrTXZWepYVoGPNXni6JG1L3BhGq/go-bitswap/decision" "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" @@ -32,6 +32,10 @@ var BitswapCmd = &cmds.Command{ }, } +const ( + peerOptionName = "peer" +) + var showWantlistCmd = &oldcmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Show blocks currently on the wantlist.", @@ -39,7 +43,7 @@ var showWantlistCmd = &oldcmds.Command{ Print out all blocks currently on the bitswap wantlist for the local peer.`, }, Options: []cmdkit.Option{ - cmdkit.StringOption("peer", "p", "Specify which peer to show wantlist for. Default: self."), + cmdkit.StringOption(peerOptionName, "p", "Specify which peer to show wantlist for. Default: self."), }, Type: KeyList{}, Run: func(req oldcmds.Request, res oldcmds.Response) { @@ -60,7 +64,7 @@ Print out all blocks currently on the bitswap wantlist for the local peer.`, return } - pstr, found, err := req.Option("peer").String() + pstr, found, err := req.Option(peerOptionName).String() if err != nil { res.SetError(err, cmdkit.ErrNormal) return diff --git a/core/commands/block.go b/core/commands/block.go index 05cc66132..1ac1f6777 100644 --- a/core/commands/block.go +++ b/core/commands/block.go @@ -126,6 +126,12 @@ It outputs to stdout, and is a base58 encoded multihash. }, } +const ( + blockFormatOptionName = "format" + mhtypeOptionName = "mhtype" + mhlenOptionName = "mhlen" +) + var blockPutCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Store input as an IPFS block.", @@ -142,9 +148,9 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. cmdkit.FileArg("data", true, false, "The data to be stored as an IPFS block.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.StringOption("format", "f", "cid format for blocks to be created with."), - cmdkit.StringOption("mhtype", "multihash hash function").WithDefault("sha2-256"), - cmdkit.IntOption("mhlen", "multihash hash length").WithDefault(-1), + cmdkit.StringOption(blockFormatOptionName, "f", "cid format for blocks to be created with."), + cmdkit.StringOption(mhtypeOptionName, "multihash hash function").WithDefault("sha2-256"), + cmdkit.IntOption(mhlenOptionName, "multihash hash length").WithDefault(-1), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env) @@ -157,18 +163,18 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. return err } - mhtype, _ := req.Options["mhtype"].(string) + mhtype, _ := req.Options[mhtypeOptionName].(string) mhtval, ok := mh.Names[mhtype] if !ok { return fmt.Errorf("unrecognized multihash function: %s", mhtype) } - mhlen, ok := req.Options["mhlen"].(int) + mhlen, ok := req.Options[mhlenOptionName].(int) if !ok { return errors.New("missing option \"mhlen\"") } - format, formatSet := req.Options["format"].(string) + format, formatSet := req.Options[blockFormatOptionName].(string) if !formatSet { if mhtval != mh.SHA2_256 || (mhlen != -1 && mhlen != 32) { format = "protobuf" @@ -200,6 +206,11 @@ than 'sha2-256' or format to anything other than 'v0' will result in CIDv1. Type: BlockStat{}, } +const ( + forceOptionName = "force" + blockQuietOptionName = "quiet" +) + var blockRmCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Remove IPFS block(s).", @@ -212,8 +223,8 @@ It takes a list of base58 encoded multihashes to remove. cmdkit.StringArg("hash", true, true, "Bash58 encoded multihash of block(s) to remove."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("force", "f", "Ignore nonexistent blocks."), - cmdkit.BoolOption("quiet", "q", "Write minimal output."), + cmdkit.BoolOption(forceOptionName, "f", "Ignore nonexistent blocks."), + cmdkit.BoolOption(blockQuietOptionName, "q", "Write minimal output."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env) @@ -221,8 +232,8 @@ It takes a list of base58 encoded multihashes to remove. return err } - force, _ := req.Options["force"].(bool) - quiet, _ := req.Options["quiet"].(bool) + force, _ := req.Options[forceOptionName].(bool) + quiet, _ := req.Options[blockQuietOptionName].(bool) // TODO: use batching coreapi when done for _, b := range req.Arguments { diff --git a/core/commands/bootstrap.go b/core/commands/bootstrap.go index 52c51c71b..adc0333a4 100644 --- a/core/commands/bootstrap.go +++ b/core/commands/bootstrap.go @@ -12,7 +12,7 @@ import ( "github.com/ipfs/go-ipfs/repo/fsrepo" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) type BootstrapOutput struct { @@ -40,6 +40,10 @@ Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'. }, } +const ( + defaultOptionName = "default" +) + var bootstrapAddCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Add peers to the bootstrap list.", @@ -53,14 +57,14 @@ in the bootstrap list). }, Options: []cmdkit.Option{ - cmdkit.BoolOption("default", "Add default bootstrap nodes. (Deprecated, use 'default' subcommand instead)"), + cmdkit.BoolOption(defaultOptionName, "Add default bootstrap nodes. (Deprecated, use 'default' subcommand instead)"), }, Subcommands: map[string]*cmds.Command{ "default": bootstrapAddDefaultCmd, }, Run: func(req cmds.Request, res cmds.Response) { - deflt, _, err := req.Option("default").Bool() + deflt, _, err := req.Option(defaultOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -191,6 +195,10 @@ in the bootstrap list).`, }, } +const ( + bootstrapAllOptionName = "all" +) + var bootstrapRemoveCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Remove peers from the bootstrap list.", @@ -202,13 +210,13 @@ var bootstrapRemoveCmd = &cmds.Command{ cmdkit.StringArg("peer", false, true, peerOptionDesc).EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("all", "Remove all bootstrap peers. (Deprecated, use 'all' subcommand)"), + cmdkit.BoolOption(bootstrapAllOptionName, "Remove all bootstrap peers. (Deprecated, use 'all' subcommand)"), }, Subcommands: map[string]*cmds.Command{ "all": bootstrapRemoveAllCmd, }, Run: func(req cmds.Request, res cmds.Response) { - all, _, err := req.Option("all").Bool() + all, _, err := req.Option(bootstrapAllOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return diff --git a/core/commands/cat.go b/core/commands/cat.go index 125d6a3ed..3c9bb97f3 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -6,15 +6,18 @@ import ( "io" "os" - core "github.com/ipfs/go-ipfs/core" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" - coreunix "github.com/ipfs/go-ipfs/core/coreunix" + "github.com/ipfs/go-ipfs/core/coreapi/interface" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ) -const progressBarMinSize = 1024 * 1024 * 8 // show progress bar for outputs > 8MiB +const ( + progressBarMinSize = 1024 * 1024 * 8 // show progress bar for outputs > 8MiB + offsetOptionName = "offset" + lengthOptionName = "length" +) var CatCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ @@ -26,8 +29,8 @@ var CatCmd = &cmds.Command{ cmdkit.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to be outputted.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.IntOption("offset", "o", "Byte offset to begin reading from."), - cmdkit.IntOption("length", "l", "Maximum number of bytes to read."), + cmdkit.IntOption(offsetOptionName, "o", "Byte offset to begin reading from."), + cmdkit.IntOption(lengthOptionName, "l", "Maximum number of bytes to read."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { node, err := cmdenv.GetNode(env) @@ -35,18 +38,23 @@ var CatCmd = &cmds.Command{ return err } + api, err := cmdenv.GetApi(env) + if err != nil { + return err + } + if !node.OnlineMode() { if err := node.SetupOfflineRouting(); err != nil { return err } } - offset, _ := req.Options["offset"].(int) + offset, _ := req.Options[offsetOptionName].(int) if offset < 0 { return fmt.Errorf("cannot specify negative offset") } - max, found := req.Options["length"].(int) + max, found := req.Options[lengthOptionName].(int) if err != nil { return err } @@ -62,7 +70,7 @@ var CatCmd = &cmds.Command{ return err } - readers, length, err := cat(req.Context, node, req.Arguments, int64(offset), int64(max)) + readers, length, err := cat(req.Context, api, req.Arguments, int64(offset), int64(max)) if err != nil { return err } @@ -115,14 +123,19 @@ var CatCmd = &cmds.Command{ }, } -func cat(ctx context.Context, node *core.IpfsNode, paths []string, offset int64, max int64) ([]io.Reader, uint64, error) { +func cat(ctx context.Context, api iface.CoreAPI, paths []string, offset int64, max int64) ([]io.Reader, uint64, error) { readers := make([]io.Reader, 0, len(paths)) length := uint64(0) if max == 0 { return nil, 0, nil } - for _, fpath := range paths { - read, err := coreunix.Cat(ctx, node, fpath) + for _, p := range paths { + fpath, err := iface.ParsePath(p) + if err != nil { + return nil, 0, err + } + + read, err := api.Unixfs().Cat(ctx, fpath) if err != nil { return nil, 0, err } diff --git a/core/commands/cid.go b/core/commands/cid.go new file mode 100644 index 000000000..7af002fb8 --- /dev/null +++ b/core/commands/cid.go @@ -0,0 +1,364 @@ +package commands + +import ( + "fmt" + "io" + "sort" + "strings" + "unicode" + + "github.com/ipfs/go-ipfs/core/commands/e" + + cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mhash "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" + cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" + cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + verifcid "gx/ipfs/QmVkMRSkXrpjqrroEXWuYBvDBnXCdMMY6gsKicBGVGUqKT/go-verifcid" + cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" + mbase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase" +) + +var CidCmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "Convert and discover properties of CIDs", + }, + Subcommands: map[string]*cmds.Command{ + "format": cidFmtCmd, + "base32": base32Cmd, + "bases": basesCmd, + "codecs": codecsCmd, + "hashes": hashesCmd, + }, +} + +const ( + cidFormatOptionName = "f" + cidVerisonOptionName = "v" + cidMultibaseOptionName = "b" +) + +var cidFmtCmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "Format and convert a CID in various useful ways.", + LongDescription: ` +Format and converts 's in various useful ways. + +The optional format string is a printf style format string: +` + cidutil.FormatRef, + }, + Arguments: []cmdkit.Argument{ + cmdkit.StringArg("cid", true, true, "Cids to format.").EnableStdin(), + }, + Options: []cmdkit.Option{ + cmdkit.StringOption(cidFormatOptionName, "Printf style format string.").WithDefault("%s"), + cmdkit.StringOption(cidVerisonOptionName, "CID version to convert to."), + cmdkit.StringOption(cidMultibaseOptionName, "Multibase to display CID in."), + }, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + fmtStr, _ := req.Options[cidFormatOptionName].(string) + verStr, _ := req.Options[cidVerisonOptionName].(string) + baseStr, _ := req.Options[cidMultibaseOptionName].(string) + + opts := cidFormatOpts{} + + if strings.IndexByte(fmtStr, '%') == -1 { + return fmt.Errorf("invalid format string: %s", fmtStr) + } + opts.fmtStr = fmtStr + + switch verStr { + case "": + // noop + case "0": + opts.verConv = toCidV0 + case "1": + opts.verConv = toCidV1 + default: + return fmt.Errorf("invalid cid version: %s", verStr) + } + + if baseStr != "" { + encoder, err := mbase.EncoderByName(baseStr) + if err != nil { + return err + } + opts.newBase = encoder.Encoding() + } else { + opts.newBase = mbase.Encoding(-1) + } + + return emitCids(req, resp, opts) + }, + PostRun: cmds.PostRunMap{ + cmds.CLI: streamResult(func(v interface{}, out io.Writer) nonFatalError { + r := v.(*CidFormatRes) + if r.ErrorMsg != "" { + return nonFatalError(fmt.Sprintf("%s: %s", r.CidStr, r.ErrorMsg)) + } + fmt.Fprintf(out, "%s\n", r.Formatted) + return "" + }), + }, + Type: CidFormatRes{}, +} + +type CidFormatRes struct { + CidStr string // Original Cid String passed in + Formatted string // Formated Result + ErrorMsg string // Error +} + +var base32Cmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "Convert CIDs to Base32 CID version 1.", + }, + Arguments: []cmdkit.Argument{ + cmdkit.StringArg("cid", true, true, "Cids to convert.").EnableStdin(), + }, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + opts := cidFormatOpts{ + fmtStr: "%s", + newBase: mbase.Encoding(mbase.Base32), + verConv: toCidV1, + } + return emitCids(req, resp, opts) + }, + PostRun: cidFmtCmd.PostRun, + Type: cidFmtCmd.Type, +} + +type cidFormatOpts struct { + fmtStr string + newBase mbase.Encoding + verConv func(cid cid.Cid) (cid.Cid, error) +} + +type argumentIterator struct { + args []string + body cmds.StdinArguments +} + +func (i *argumentIterator) next() (string, bool) { + if len(i.args) > 0 { + arg := i.args[0] + i.args = i.args[1:] + return arg, true + } + if i.body == nil || !i.body.Scan() { + return "", false + } + return strings.TrimSpace(i.body.Argument()), true +} + +func (i *argumentIterator) err() error { + if i.body == nil { + return nil + } + return i.body.Err() +} + +func emitCids(req *cmds.Request, resp cmds.ResponseEmitter, opts cidFormatOpts) error { + itr := argumentIterator{req.Arguments, req.BodyArgs()} + var emitErr error + for emitErr == nil { + cidStr, ok := itr.next() + if !ok { + break + } + res := &CidFormatRes{CidStr: cidStr} + c, err := cid.Decode(cidStr) + if err != nil { + res.ErrorMsg = err.Error() + emitErr = resp.Emit(res) + continue + } + base := opts.newBase + if base == -1 { + base, _ = cid.ExtractEncoding(cidStr) + } + if opts.verConv != nil { + c, err = opts.verConv(c) + if err != nil { + res.ErrorMsg = err.Error() + emitErr = resp.Emit(res) + continue + } + } + str, err := cidutil.Format(opts.fmtStr, base, c) + if _, ok := err.(cidutil.FormatStringError); ok { + // no point in continuing if there is a problem with the format string + return err + } + if err != nil { + res.ErrorMsg = err.Error() + } else { + res.Formatted = str + } + emitErr = resp.Emit(res) + } + if emitErr != nil { + return emitErr + } + err := itr.err() + if err != nil { + return err + } + return nil +} + +func toCidV0(c cid.Cid) (cid.Cid, error) { + if c.Type() != cid.DagProtobuf { + return cid.Cid{}, fmt.Errorf("can't convert non-protobuf nodes to cidv0") + } + return cid.NewCidV0(c.Hash()), nil +} + +func toCidV1(c cid.Cid) (cid.Cid, error) { + return cid.NewCidV1(c.Type(), c.Hash()), nil +} + +type CodeAndName struct { + Code int + Name string +} + +const ( + prefixOptionName = "prefix" + numericOptionName = "numeric" +) + +var basesCmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "List available multibase encodings.", + }, + Options: []cmdkit.Option{ + cmdkit.BoolOption(prefixOptionName, "also include the single leter prefixes in addition to the code"), + cmdkit.BoolOption(numericOptionName, "also include numeric codes"), + }, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + var res []CodeAndName + // use EncodingToStr in case at some point there are multiple names for a given code + for code, name := range mbase.EncodingToStr { + res = append(res, CodeAndName{int(code), name}) + } + cmds.EmitOnce(resp, res) + return nil + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, val0 interface{}) error { + prefixes, _ := req.Options[prefixOptionName].(bool) + numeric, _ := req.Options[numericOptionName].(bool) + val, ok := val0.([]CodeAndName) + if !ok { + return e.TypeErr(val, val0) + } + sort.Sort(multibaseSorter{val}) + for _, v := range val { + code := v.Code + if code < 32 || code >= 127 { + // don't display non-printable prefixes + code = ' ' + } + switch { + case prefixes && numeric: + fmt.Fprintf(w, "%c %5d %s\n", code, v.Code, v.Name) + case prefixes: + fmt.Fprintf(w, "%c %s\n", code, v.Name) + case numeric: + fmt.Fprintf(w, "%5d %s\n", v.Code, v.Name) + default: + fmt.Fprintf(w, "%s\n", v.Name) + } + } + return nil + }), + }, + Type: []CodeAndName{}, +} + +const ( + codecsNumericOptionName = "numeric" +) + +var codecsCmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "List available CID codecs.", + }, + Options: []cmdkit.Option{ + cmdkit.BoolOption(codecsNumericOptionName, "also include numeric codes"), + }, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + var res []CodeAndName + // use CodecToStr as there are multiple names for a given code + for code, name := range cid.CodecToStr { + res = append(res, CodeAndName{int(code), name}) + } + cmds.EmitOnce(resp, res) + return nil + }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, val0 interface{}) error { + numeric, _ := req.Options[codecsNumericOptionName].(bool) + val, ok := val0.([]CodeAndName) + if !ok { + return e.TypeErr(val, val0) + } + sort.Sort(codeAndNameSorter{val}) + for _, v := range val { + if numeric { + fmt.Fprintf(w, "%5d %s\n", v.Code, v.Name) + } else { + fmt.Fprintf(w, "%s\n", v.Name) + } + } + return nil + }), + }, + Type: []CodeAndName{}, +} + +var hashesCmd = &cmds.Command{ + Helptext: cmdkit.HelpText{ + Tagline: "List available multihashes.", + }, + Options: codecsCmd.Options, + Run: func(req *cmds.Request, resp cmds.ResponseEmitter, env cmds.Environment) error { + var res []CodeAndName + // use mhash.Codes in case at some point there are multiple names for a given code + for code, name := range mhash.Codes { + if !verifcid.IsGoodHash(code) { + continue + } + res = append(res, CodeAndName{int(code), name}) + } + cmds.EmitOnce(resp, res) + return nil + }, + Encoders: codecsCmd.Encoders, + Type: codecsCmd.Type, +} + +type multibaseSorter struct { + data []CodeAndName +} + +func (s multibaseSorter) Len() int { return len(s.data) } +func (s multibaseSorter) Swap(i, j int) { s.data[i], s.data[j] = s.data[j], s.data[i] } + +func (s multibaseSorter) Less(i, j int) bool { + a := unicode.ToLower(rune(s.data[i].Code)) + b := unicode.ToLower(rune(s.data[j].Code)) + if a != b { + return a < b + } + // lowecase letters should come before uppercase + return s.data[i].Code > s.data[j].Code +} + +type codeAndNameSorter struct { + data []CodeAndName +} + +func (s codeAndNameSorter) Len() int { return len(s.data) } +func (s codeAndNameSorter) Swap(i, j int) { s.data[i], s.data[j] = s.data[j], s.data[i] } +func (s codeAndNameSorter) Less(i, j int) bool { return s.data[i].Code < s.data[j].Code } diff --git a/core/commands/cmdenv/env.go b/core/commands/cmdenv/env.go index 757c2c962..4da7b1e7a 100644 --- a/core/commands/cmdenv/env.go +++ b/core/commands/cmdenv/env.go @@ -7,7 +7,7 @@ import ( "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ) diff --git a/core/commands/commands.go b/core/commands/commands.go index 51c707c6e..65757c1cf 100644 --- a/core/commands/commands.go +++ b/core/commands/commands.go @@ -8,6 +8,7 @@ package commands import ( "fmt" "io" + "os" "sort" "strings" @@ -149,3 +150,42 @@ func unwrapOutput(i interface{}) (interface{}, error) { return <-ch, nil } + +type nonFatalError string + +// streamResult is a helper function to stream results that possibly +// contain non-fatal errors. The helper function is allowed to panic +// on internal errors. +func streamResult(procVal func(interface{}, io.Writer) nonFatalError) func(cmds.Response, cmds.ResponseEmitter) error { + return func(res cmds.Response, re cmds.ResponseEmitter) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("internal error: %v", r) + } + re.Close() + }() + + var errors bool + for { + v, err := res.Next() + if err != nil { + if err == io.EOF { + break + } + return err + } + + errorMsg := procVal(v, os.Stdout) + + if errorMsg != "" { + errors = true + fmt.Fprintf(os.Stderr, "%s\n", errorMsg) + } + } + + if errors { + return fmt.Errorf("errors while displaying some entries") + } + return nil + } +} diff --git a/core/commands/commands_test.go b/core/commands/commands_test.go index ec4b4ba5f..74d589034 100644 --- a/core/commands/commands_test.go +++ b/core/commands/commands_test.go @@ -211,6 +211,12 @@ func TestCommands(t *testing.T) { "/urlstore", "/urlstore/add", "/version", + "/cid", + "/cid/format", + "/cid/base32", + "/cid/codecs", + "/cid/bases", + "/cid/hashes", } cmdSet := make(map[string]struct{}) diff --git a/core/commands/config.go b/core/commands/config.go index 0230d112c..b451b3d09 100644 --- a/core/commands/config.go +++ b/core/commands/config.go @@ -17,7 +17,7 @@ import ( fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) type ConfigField struct { @@ -25,6 +25,11 @@ type ConfigField struct { Value interface{} } +const ( + configBoolOptionName = "bool" + configJSONOptionName = "json" +) + var ConfigCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Get and set ipfs config values.", @@ -54,8 +59,8 @@ Set the value of the 'Datastore.Path' key: cmdkit.StringArg("value", false, false, "The value to set the config entry to."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("bool", "Set a boolean value."), - cmdkit.BoolOption("json", "Parse stringified JSON."), + cmdkit.BoolOption(configBoolOptionName, "Set a boolean value."), + cmdkit.BoolOption(configJSONOptionName, "Parse stringified JSON."), }, Run: func(req cmds.Request, res cmds.Response) { args := req.Arguments() @@ -87,7 +92,7 @@ Set the value of the 'Datastore.Path' key: if len(args) == 2 { value := args[1] - if parseJson, _, _ := req.Option("json").Bool(); parseJson { + if parseJSON, _, _ := req.Option(configJSONOptionName).Bool(); parseJSON { var jsonVal interface{} if err := json.Unmarshal([]byte(value), &jsonVal); err != nil { err = fmt.Errorf("failed to unmarshal json. %s", err) @@ -96,7 +101,7 @@ Set the value of the 'Datastore.Path' key: } output, err = setConfig(r, key, jsonVal) - } else if isbool, _, _ := req.Option("bool").Bool(); isbool { + } else if isbool, _, _ := req.Option(configBoolOptionName).Bool(); isbool { output, err = setConfig(r, key, value == "true") } else { output, err = setConfig(r, key, value) diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 0191a8c1f..f206edef3 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -11,7 +11,7 @@ import ( e "github.com/ipfs/go-ipfs/core/commands/e" coredag "github.com/ipfs/go-ipfs/core/coredag" pin "github.com/ipfs/go-ipfs/pin" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" diff --git a/core/commands/dht.go b/core/commands/dht.go index c8aac231c..dbf2cac05 100644 --- a/core/commands/dht.go +++ b/core/commands/dht.go @@ -10,17 +10,17 @@ import ( cmds "github.com/ipfs/go-ipfs/commands" e "github.com/ipfs/go-ipfs/core/commands/e" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" - notif "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing/notifications" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + notif "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing/notifications" b58 "gx/ipfs/QmWFAMPqsEyUX7gDUsRVmMWz59FxSpJ1b2v6bJ1yYzo7jY/go-base58-fast/base58" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) var ErrNotDHT = errors.New("routing service is not a DHT") @@ -44,6 +44,10 @@ var DhtCmd = &cmds.Command{ }, } +const ( + dhtVerboseOptionName = "v" +) + var queryDhtCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Find the closest Peer IDs to a given Peer ID by querying the DHT.", @@ -54,7 +58,7 @@ var queryDhtCmd = &cmds.Command{ cmdkit.StringArg("peerID", true, true, "The peerID to run the query against."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -128,7 +132,7 @@ var queryDhtCmd = &cmds.Command{ return nil, e.TypeErr(obj, v) } - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() buf := new(bytes.Buffer) printEvent(obj, buf, verbose, pfm) @@ -139,6 +143,10 @@ var queryDhtCmd = &cmds.Command{ Type: notif.QueryEvent{}, } +const ( + numProvidersOptionName = "num-providers" +) + var findProvidersDhtCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Find peers that can provide a specific value, given a key.", @@ -149,8 +157,8 @@ var findProvidersDhtCmd = &cmds.Command{ cmdkit.StringArg("key", true, true, "The key to find providers for."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), - cmdkit.IntOption("num-providers", "n", "The number of providers to find.").WithDefault(20), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), + cmdkit.IntOption(numProvidersOptionName, "n", "The number of providers to find.").WithDefault(20), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -164,7 +172,7 @@ var findProvidersDhtCmd = &cmds.Command{ return } - numProviders, _, err := res.Request().Option("num-providers").Int() + numProviders, _, err := res.Request().Option(numProvidersOptionName).Int() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -232,7 +240,7 @@ var findProvidersDhtCmd = &cmds.Command{ } return func(res cmds.Response) (io.Reader, error) { - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() v, err := unwrapOutput(res.Output()) if err != nil { return nil, err @@ -252,6 +260,10 @@ var findProvidersDhtCmd = &cmds.Command{ Type: notif.QueryEvent{}, } +const ( + recursiveOptionName = "recursive" +) + var provideRefDhtCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Announce to the network that you are providing given values.", @@ -261,8 +273,8 @@ var provideRefDhtCmd = &cmds.Command{ cmdkit.StringArg("key", true, true, "The key[s] to send provide records for.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), - cmdkit.BoolOption("recursive", "r", "Recursively provide entire graph."), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), + cmdkit.BoolOption(recursiveOptionName, "r", "Recursively provide entire graph."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -281,7 +293,7 @@ var provideRefDhtCmd = &cmds.Command{ return } - rec, _, _ := req.Option("recursive").Bool() + rec, _, _ := req.Option(recursiveOptionName).Bool() var cids []cid.Cid for _, arg := range req.Arguments() { @@ -349,7 +361,7 @@ var provideRefDhtCmd = &cmds.Command{ } return func(res cmds.Response) (io.Reader, error) { - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() v, err := unwrapOutput(res.Output()) if err != nil { return nil, err @@ -414,7 +426,7 @@ var findPeerDhtCmd = &cmds.Command{ cmdkit.StringArg("peerID", true, true, "The ID of the peer to search for."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -480,7 +492,7 @@ var findPeerDhtCmd = &cmds.Command{ } return func(res cmds.Response) (io.Reader, error) { - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() v, err := unwrapOutput(res.Output()) if err != nil { return nil, err @@ -519,7 +531,7 @@ Different key types can specify other 'best' rules. cmdkit.StringArg("key", true, true, "The key to find a value for."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -584,7 +596,7 @@ Different key types can specify other 'best' rules. } return func(res cmds.Response) (io.Reader, error) { - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() v, err := unwrapOutput(res.Output()) if err != nil { return nil, err @@ -633,7 +645,7 @@ NOTE: A value may not exceed 2048 bytes. cmdkit.StringArg("value", true, false, "The value to store.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "Print extra information."), + cmdkit.BoolOption("verbose", dhtVerboseOptionName, "Print extra information."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -697,7 +709,7 @@ NOTE: A value may not exceed 2048 bytes. } return func(res cmds.Response) (io.Reader, error) { - verbose, _, _ := res.Request().Option("v").Bool() + verbose, _, _ := res.Request().Option(dhtVerboseOptionName).Bool() v, err := unwrapOutput(res.Output()) if err != nil { return nil, err diff --git a/core/commands/dht_test.go b/core/commands/dht_test.go index e4f582ff0..c47f09e6d 100644 --- a/core/commands/dht_test.go +++ b/core/commands/dht_test.go @@ -6,7 +6,7 @@ import ( "github.com/ipfs/go-ipfs/namesys" tu "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" ) func TestKeyTranslation(t *testing.T) { diff --git a/core/commands/dns.go b/core/commands/dns.go index 2353ee7ec..236630813 100644 --- a/core/commands/dns.go +++ b/core/commands/dns.go @@ -13,6 +13,10 @@ import ( "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" ) +const ( + dnsRecursiveOptionName = "recursive" +) + var DNSCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Resolve DNS links.", @@ -51,11 +55,11 @@ The resolver can recursively resolve: cmdkit.StringArg("domain-name", true, false, "The domain-name name to resolve.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("recursive", "r", "Resolve until the result is not a DNS link."), + cmdkit.BoolOption(dnsRecursiveOptionName, "r", "Resolve until the result is not a DNS link."), }, Run: func(req cmds.Request, res cmds.Response) { - recursive, _, _ := req.Option("recursive").Bool() + recursive, _, _ := req.Option(dnsRecursiveOptionName).Bool() name := req.Arguments()[0] resolver := namesys.NewDNSResolver() diff --git a/core/commands/files.go b/core/commands/files.go index 7ad62dabf..356a16cf4 100644 --- a/core/commands/files.go +++ b/core/commands/files.go @@ -16,21 +16,19 @@ import ( core "github.com/ipfs/go-ipfs/core" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" e "github.com/ipfs/go-ipfs/core/commands/e" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + "github.com/ipfs/go-ipfs/core/coreapi/interface" humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bservice "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -71,8 +69,13 @@ operations. }, } -var cidVersionOption = cmdkit.IntOption("cid-version", "cid-ver", "Cid version to use. (experimental)") -var hashOption = cmdkit.StringOption("hash", "Hash function to use. Will set Cid version to 1 if used. (experimental)") +const ( + filesCidVersionOptionName = "cid-version" + filesHashOptionName = "hash" +) + +var cidVersionOption = cmdkit.IntOption(filesCidVersionOptionName, "cid-ver", "Cid version to use. (experimental)") +var hashOption = cmdkit.StringOption(filesHashOptionName, "Hash function to use. Will set Cid version to 1 if used. (experimental)") var errFormat = errors.New("format was set by multiple options. Only one format option is allowed") @@ -87,11 +90,16 @@ type statOutput struct { SizeLocal uint64 `json:",omitempty"` } -const defaultStatFormat = ` +const ( + defaultStatFormat = ` Size: CumulativeSize: ChildBlocks: Type: ` + filesFormatOptionName = "format" + filesSizeOptionName = "size" + filesWithLocalOptionName = "with-local" +) var filesStatCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ @@ -102,11 +110,11 @@ var filesStatCmd = &cmds.Command{ cmdkit.StringArg("path", true, false, "Path to node to stat."), }, Options: []cmdkit.Option{ - cmdkit.StringOption("format", "Print statistics in given format. Allowed tokens: "+ + cmdkit.StringOption(filesFormatOptionName, "Print statistics in given format. Allowed tokens: "+ " . Conflicts with other format options.").WithDefault(defaultStatFormat), - cmdkit.BoolOption("hash", "Print only hash. Implies '--format='. Conflicts with other format options."), - cmdkit.BoolOption("size", "Print only size. Implies '--format='. Conflicts with other format options."), - cmdkit.BoolOption("with-local", "Compute the amount of the dag that is local, and if possible the total size"), + cmdkit.BoolOption(filesHashOptionName, "Print only hash. Implies '--format='. Conflicts with other format options."), + cmdkit.BoolOption(filesSizeOptionName, "Print only size. Implies '--format='. Conflicts with other format options."), + cmdkit.BoolOption(filesWithLocalOptionName, "Compute the amount of the dag that is local, and if possible the total size"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { @@ -120,12 +128,17 @@ var filesStatCmd = &cmds.Command{ return err } + api, err := cmdenv.GetApi(env) + if err != nil { + return err + } + path, err := checkPath(req.Arguments[0]) if err != nil { return err } - withLocal, _ := req.Options["with-local"].(bool) + withLocal, _ := req.Options[filesWithLocalOptionName].(bool) var dagserv ipld.DAGService if withLocal { @@ -138,7 +151,7 @@ var filesStatCmd = &cmds.Command{ dagserv = node.DAG } - nd, err := getNodeFromPath(req.Context, node, dagserv, path) + nd, err := getNodeFromPath(req.Context, node, api, path) if err != nil { return err } @@ -196,9 +209,9 @@ func moreThanOne(a, b, c bool) bool { func statGetFormatOptions(req *cmds.Request) (string, error) { - hash, _ := req.Options["hash"].(bool) - size, _ := req.Options["size"].(bool) - format, _ := req.Options["format"].(string) + hash, _ := req.Options[filesHashOptionName].(bool) + size, _ := req.Options[filesSizeOptionName].(bool) + format, _ := req.Options[filesFormatOptionName].(string) if moreThanOne(hash, size, format != defaultStatFormat) { return "", errFormat @@ -305,6 +318,12 @@ var filesCpCmd = &oldcmds.Command{ return } + api, err := req.InvocContext().GetApi() + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + flush, _, _ := req.Option("flush").Bool() src, err := checkPath(req.Arguments()[0]) @@ -324,7 +343,7 @@ var filesCpCmd = &oldcmds.Command{ dst += gopath.Base(src) } - nd, err := getNodeFromPath(req.Context(), node, node.DAG, src) + nd, err := getNodeFromPath(req.Context(), node, api, src) if err != nil { res.SetError(fmt.Errorf("cp: cannot get node from path %s: %s", src, err), cmdkit.ErrNormal) return @@ -348,20 +367,15 @@ var filesCpCmd = &oldcmds.Command{ }, } -func getNodeFromPath(ctx context.Context, node *core.IpfsNode, dagservice ipld.DAGService, p string) (ipld.Node, error) { +func getNodeFromPath(ctx context.Context, node *core.IpfsNode, api iface.CoreAPI, p string) (ipld.Node, error) { switch { case strings.HasPrefix(p, "/ipfs/"): - np, err := path.ParsePath(p) + np, err := iface.ParsePath(p) if err != nil { return nil, err } - resolver := &resolver.Resolver{ - DAG: dagservice, - ResolveOnce: uio.ResolveUnixfsOnce, - } - - return core.Resolve(ctx, node.Namesys, resolver, np) + return api.ResolveNode(ctx, np) default: fsn, err := mfs.Lookup(node.FilesRoot, p) if err != nil { @@ -376,6 +390,11 @@ type filesLsOutput struct { Entries []mfs.NodeListing } +const ( + longOptionName = "l" + dontSortOptionName = "U" +) + var filesLsCmd = &oldcmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List directories in the local mutable namespace.", @@ -401,8 +420,8 @@ Examples: cmdkit.StringArg("path", false, false, "Path to show listing for. Defaults to '/'."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("l", "Use long listing format."), - cmdkit.BoolOption("U", "Do not sort; list entries in directory order."), + cmdkit.BoolOption(longOptionName, "Use long listing format."), + cmdkit.BoolOption(dontSortOptionName, "Do not sort; list entries in directory order."), }, Run: func(req oldcmds.Request, res oldcmds.Response) { var arg string @@ -431,7 +450,7 @@ Examples: return } - long, _, _ := req.Option("l").Bool() + long, _, _ := req.Option(longOptionName).Bool() switch fsn := fsn.(type) { case *mfs.Directory: @@ -498,14 +517,14 @@ Examples: buf := new(bytes.Buffer) - noSort, _, _ := res.Request().Option("U").Bool() + noSort, _, _ := res.Request().Option(dontSortOptionName).Bool() if !noSort { sort.Slice(out.Entries, func(i, j int) bool { return strings.Compare(out.Entries[i].Name, out.Entries[j].Name) < 0 }) } - long, _, _ := res.Request().Option("l").Bool() + long, _, _ := res.Request().Option(longOptionName).Bool() for _, o := range out.Entries { if long { fmt.Fprintf(buf, "%s\t%s\t%d\n", o.Name, o.Hash, o.Size) @@ -519,6 +538,11 @@ Examples: Type: filesLsOutput{}, } +const ( + filesOffsetOptionName = "offset" + filesCountOptionName = "count" +) + var filesReadCmd = &oldcmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Read a file in a given mfs.", @@ -537,8 +561,8 @@ Examples: cmdkit.StringArg("path", true, false, "Path to file to be read."), }, Options: []cmdkit.Option{ - cmdkit.IntOption("offset", "o", "Byte offset to begin reading from."), - cmdkit.IntOption("count", "n", "Maximum number of bytes to read."), + cmdkit.IntOption(filesOffsetOptionName, "o", "Byte offset to begin reading from."), + cmdkit.IntOption(filesCountOptionName, "n", "Maximum number of bytes to read."), }, Run: func(req oldcmds.Request, res oldcmds.Response) { n, err := req.InvocContext().GetNode() @@ -573,7 +597,7 @@ Examples: defer rfd.Close() - offset, _, err := req.Option("offset").Int() + offset, _, err := req.Option(offsetOptionName).Int() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -601,7 +625,7 @@ Examples: } var r io.Reader = &contextReaderWrapper{R: rfd, ctx: req.Context()} - count, found, err := req.Option("count").Int() + count, found, err := req.Option(filesCountOptionName).Int() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -676,6 +700,14 @@ Example: }, } +const ( + filesCreateOptionName = "create" + filesParentsOptionName = "parents" + filesTruncateOptionName = "truncate" + filesRawLeavesOptionName = "raw-leaves" + filesFlushOptionName = "flush" +) + var filesWriteCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Write to a mutable file in a given filesystem.", @@ -715,12 +747,12 @@ stat' on the file or any of its ancestors. cmdkit.FileArg("data", true, false, "Data to write.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.IntOption("offset", "o", "Byte offset to begin writing at."), - cmdkit.BoolOption("create", "e", "Create the file if it does not exist."), - cmdkit.BoolOption("parents", "p", "Make parent directories as needed."), - cmdkit.BoolOption("truncate", "t", "Truncate the file to size zero before writing."), - cmdkit.IntOption("count", "n", "Maximum number of bytes to read."), - cmdkit.BoolOption("raw-leaves", "Use raw blocks for newly created leaf nodes. (experimental)"), + cmdkit.IntOption(filesOffsetOptionName, "o", "Byte offset to begin writing at."), + cmdkit.BoolOption(filesCreateOptionName, "e", "Create the file if it does not exist."), + cmdkit.BoolOption(filesParentsOptionName, "p", "Make parent directories as needed."), + cmdkit.BoolOption(filesTruncateOptionName, "t", "Truncate the file to size zero before writing."), + cmdkit.IntOption(filesCountOptionName, "n", "Maximum number of bytes to read."), + cmdkit.BoolOption(filesRawLeavesOptionName, "Use raw blocks for newly created leaf nodes. (experimental)"), cidVersionOption, hashOption, }, @@ -730,11 +762,11 @@ stat' on the file or any of its ancestors. return err } - create, _ := req.Options["create"].(bool) - mkParents, _ := req.Options["parents"].(bool) - trunc, _ := req.Options["truncate"].(bool) - flush, _ := req.Options["flush"].(bool) - rawLeaves, rawLeavesDef := req.Options["raw-leaves"].(bool) + create, _ := req.Options[filesCreateOptionName].(bool) + mkParents, _ := req.Options[filesParentsOptionName].(bool) + trunc, _ := req.Options[filesTruncateOptionName].(bool) + flush, _ := req.Options[filesFlushOptionName].(bool) + rawLeaves, rawLeavesDef := req.Options[filesRawLeavesOptionName].(bool) prefix, err := getPrefixNew(req) if err != nil { @@ -746,7 +778,7 @@ stat' on the file or any of its ancestors. return err } - offset, _ := req.Options["offset"].(int) + offset, _ := req.Options[filesOffsetOptionName].(int) if offset < 0 { return fmt.Errorf("cannot have negative write offset") } @@ -788,7 +820,7 @@ stat' on the file or any of its ancestors. } } - count, countfound := req.Options["count"].(int) + count, countfound := req.Options[filesCountOptionName].(int) if countfound && count < 0 { return fmt.Errorf("cannot have negative byte count") } @@ -836,7 +868,7 @@ Examples: cmdkit.StringArg("path", true, false, "Path to dir to make."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("parents", "p", "No error if existing, make parent directories as needed."), + cmdkit.BoolOption(filesParentsOptionName, "p", "No error if existing, make parent directories as needed."), cidVersionOption, hashOption, }, @@ -847,14 +879,14 @@ Examples: return } - dashp, _, _ := req.Option("parents").Bool() + dashp, _, _ := req.Option(filesParentsOptionName).Bool() dirtomake, err := checkPath(req.Arguments()[0]) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - flush, _, _ := req.Option("flush").Bool() + flush, _, _ := req.Option(filesFlushOptionName).Bool() prefix, err := getPrefix(req) if err != nil { @@ -936,7 +968,7 @@ Change the cid version or hash function of the root node of a given path. path = req.Arguments()[0] } - flush, _, _ := req.Option("flush").Bool() + flush, _, _ := req.Option(filesFlushOptionName).Bool() prefix, err := getPrefix(req) if err != nil { @@ -998,6 +1030,7 @@ Remove files or directories. }, Options: []cmdkit.Option{ cmdkit.BoolOption("recursive", "r", "Recursively remove directories."), + cmdkit.BoolOption("force", "Forcibly remove target at path; implies -r for directories"), }, Run: func(req oldcmds.Request, res oldcmds.Response) { defer res.SetOutput(nil) @@ -1037,8 +1070,6 @@ Remove files or directories. return } - dashr, _, _ := req.Option("r").Bool() - var success bool defer func() { if success { @@ -1050,8 +1081,10 @@ Remove files or directories. } }() - // if '-r' specified, don't check file type (in bad scenarios, the block may not exist) - if dashr { + // if '--force' specified, it will remove anything else, + // including file, directory, corrupted node, etc + force, _, _ := req.Option("force").Bool() + if force { err := pdir.Unlink(name) if err != nil { res.SetError(err, cmdkit.ErrNormal) @@ -1062,31 +1095,37 @@ Remove files or directories. return } - childi, err := pdir.Child(name) + // get child node by name, when the node is corrupted and nonexistent, + // it will return specific error. + child, err := pdir.Child(name) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - switch childi.(type) { + dashr, _, _ := req.Option("r").Bool() + + switch child.(type) { case *mfs.Directory: - res.SetError(fmt.Errorf("%s is a directory, use -r to remove directories", path), cmdkit.ErrNormal) - return - default: - err := pdir.Unlink(name) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) + if !dashr { + res.SetError(fmt.Errorf("%s is a directory, use -r to remove directories", path), cmdkit.ErrNormal) return } - - success = true } + + err = pdir.Unlink(name) + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + + success = true }, } func getPrefixNew(req *cmds.Request) (cid.Builder, error) { - cidVer, cidVerSet := req.Options["cid-version"].(int) - hashFunStr, hashFunSet := req.Options["hash"].(string) + cidVer, cidVerSet := req.Options[filesCidVersionOptionName].(int) + hashFunStr, hashFunSet := req.Options[filesHashOptionName].(string) if !cidVerSet && !hashFunSet { return nil, nil @@ -1114,8 +1153,8 @@ func getPrefixNew(req *cmds.Request) (cid.Builder, error) { } func getPrefix(req oldcmds.Request) (cid.Builder, error) { - cidVer, cidVerSet, _ := req.Option("cid-version").Int() - hashFunStr, hashFunSet, _ := req.Option("hash").String() + cidVer, cidVerSet, _ := req.Option(filesCidVersionOptionName).Int() + hashFunStr, hashFunSet, _ := req.Option(filesHashOptionName).String() if !cidVerSet && !hashFunSet { return nil, nil diff --git a/core/commands/filestore.go b/core/commands/filestore.go index a45e01ef9..0376c8ead 100644 --- a/core/commands/filestore.go +++ b/core/commands/filestore.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "os" oldCmds "github.com/ipfs/go-ipfs/commands" lgc "github.com/ipfs/go-ipfs/commands/legacy" @@ -29,6 +28,10 @@ var FileStoreCmd = &cmds.Command{ }, } +const ( + fileOrderOptionName = "file-order" +) + var lsFileStore = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List objects in filestore.", @@ -47,7 +50,7 @@ The output is: cmdkit.StringArg("obj", false, true, "Cid of objects to list."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("file-order", "sort the results based on the path of the backing file"), + cmdkit.BoolOption(fileOrderOptionName, "sort the results based on the path of the backing file"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { _, fs, err := getFilestore(env) @@ -63,7 +66,7 @@ The output is: return res.Emit(out) } - fileOrder, _ := req.Options["file-order"].(bool) + fileOrder, _ := req.Options[fileOrderOptionName].(bool) next, err := filestore.ListAll(fs, fileOrder) if err != nil { return err @@ -73,36 +76,14 @@ The output is: return res.Emit(out) }, PostRun: cmds.PostRunMap{ - cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { - var errors bool - for { - v, err := res.Next() - if err != nil { - if err == io.EOF { - break - } - return err - } - - r, ok := v.(*filestore.ListRes) - if !ok { - return e.New(e.TypeErr(r, v)) - } - - if r.ErrorMsg != "" { - errors = true - fmt.Fprintf(os.Stderr, "%s\n", r.ErrorMsg) - } else { - fmt.Fprintf(os.Stdout, "%s\n", r.FormatLong()) - } + cmds.CLI: streamResult(func(v interface{}, out io.Writer) nonFatalError { + r := v.(*filestore.ListRes) + if r.ErrorMsg != "" { + return nonFatalError(r.ErrorMsg) } - - if errors { - return fmt.Errorf("errors while displaying some entries") - } - - return nil - }, + fmt.Fprintf(out, "%s\n", r.FormatLong()) + return "" + }), }, Type: filestore.ListRes{}, } @@ -135,7 +116,7 @@ For ERROR entries the error will also be printed to stderr. cmdkit.StringArg("obj", false, true, "Cid of objects to verify."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("file-order", "verify the objects based on the order of the backing file"), + cmdkit.BoolOption(fileOrderOptionName, "verify the objects based on the order of the backing file"), }, Run: func(req oldCmds.Request, res oldCmds.Response) { _, fs, err := getFilestore(req.InvocContext()) @@ -150,7 +131,7 @@ For ERROR entries the error will also be printed to stderr. }) res.SetOutput(out) } else { - fileOrder, _, _ := req.Option("file-order").Bool() + fileOrder, _, _ := req.Option(fileOrderOptionName).Bool() next, err := filestore.VerifyAll(fs, fileOrder) if err != nil { res.SetError(err, cmdkit.ErrNormal) diff --git a/core/commands/get.go b/core/commands/get.go index d82229585..b2e28f21d 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -14,16 +14,23 @@ import ( e "github.com/ipfs/go-ipfs/core/commands/e" "gx/ipfs/QmPtj12fdwuAqj9sBSTNUxBNu8kCGNp8b3o8yUzMm5GHpq/pb" + uarchive "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/archive" tar "gx/ipfs/QmQine7gvHncNevKtG9QXxf3nXcwSj6aDDmMm52mHofEEp/tar-utils" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - uarchive "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/archive" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ) var ErrInvalidCompressionLevel = errors.New("compression level must be between 1 and 9") +const ( + outputOptionName = "output" + archiveOptionName = "archive" + compressOptionName = "compress" + compressionLevelOptionName = "compression-level" +) + var GetCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Download IPFS objects.", @@ -44,10 +51,10 @@ may also specify the level of compression by specifying '-l=<1-9>'. cmdkit.StringArg("ipfs-path", true, false, "The path to the IPFS object(s) to be outputted.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.StringOption("output", "o", "The path where the output should be stored."), - cmdkit.BoolOption("archive", "a", "Output a TAR archive."), - cmdkit.BoolOption("compress", "C", "Compress the output with GZIP compression."), - cmdkit.IntOption("compression-level", "l", "The level of compression (1-9)."), + cmdkit.StringOption(outputOptionName, "o", "The path where the output should be stored."), + cmdkit.BoolOption(archiveOptionName, "a", "Output a TAR archive."), + cmdkit.BoolOption(compressOptionName, "C", "Compress the output with GZIP compression."), + cmdkit.IntOption(compressionLevelOptionName, "l", "The level of compression (1-9)."), }, PreRun: func(req *cmds.Request, env cmds.Environment) error { _, err := getCompressOptions(req) @@ -84,7 +91,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. return err } - archive, _ := req.Options["archive"].(bool) + archive, _ := req.Options[archiveOptionName].(bool) reader, err := uarchive.DagArchive(ctx, dn, p.String(), node.DAG, archive, cmplvl) if err != nil { return err @@ -113,7 +120,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. return err } - archive, _ := req.Options["archive"].(bool) + archive, _ := req.Options[archiveOptionName].(bool) gw := getWriter{ Out: os.Stdout, @@ -165,7 +172,7 @@ func makeProgressBar(out io.Writer, l int64) *pb.ProgressBar { } func getOutPath(req *cmds.Request) string { - outPath, _ := req.Options["output"].(string) + outPath, _ := req.Options[outputOptionName].(string) if outPath == "" { trimmed := strings.TrimRight(req.Arguments[0], "/") _, outPath = filepath.Split(trimmed) @@ -233,8 +240,8 @@ func (gw *getWriter) writeExtracted(r io.Reader, fpath string) error { } func getCompressOptions(req *cmds.Request) (int, error) { - cmprs, _ := req.Options["compress"].(bool) - cmplvl, cmplvlFound := req.Options["compression-level"].(int) + cmprs, _ := req.Options[compressOptionName].(bool) + cmplvl, cmplvlFound := req.Options[compressionLevelOptionName].(int) switch { case !cmprs: return gzip.NoCompression, nil diff --git a/core/commands/id.go b/core/commands/id.go index b0ae95c03..92acaa98a 100644 --- a/core/commands/id.go +++ b/core/commands/id.go @@ -13,11 +13,11 @@ import ( e "github.com/ipfs/go-ipfs/core/commands/e" ic "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - kb "gx/ipfs/QmRtUtF42geEhpRg9z45ZfBqRMC6xyeNW7i1iqha3nRMFe/go-libp2p-kbucket" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - identify "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/protocol/identify" + identify "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/protocol/identify" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + kb "gx/ipfs/Qmb4AZNKg9yQVKkQqejEcg86AaT6EqGemGV8mBjkfJBeGf/go-libp2p-kbucket" "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) const offlineIdErrorMessage = `'ipfs id' currently cannot query information on remote @@ -37,6 +37,10 @@ type IdOutput struct { ProtocolVersion string } +const ( + formatOptionName = "format" +) + var IDCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Show ipfs node id info.", @@ -60,7 +64,7 @@ EXAMPLE: cmdkit.StringArg("peerid", false, false, "Peer.ID of node to look up."), }, Options: []cmdkit.Option{ - cmdkit.StringOption("format", "f", "Optional output format."), + cmdkit.StringOption(formatOptionName, "f", "Optional output format."), }, Run: func(req cmds.Request, res cmds.Response) { node, err := req.InvocContext().GetNode() @@ -126,7 +130,7 @@ EXAMPLE: return nil, e.TypeErr(val, v) } - format, found, err := res.Request().Option("format").String() + format, found, err := res.Request().Option(formatOptionName).String() if err != nil { return nil, err } diff --git a/core/commands/keystore.go b/core/commands/keystore.go index e163a2a93..f900f6195 100644 --- a/core/commands/keystore.go +++ b/core/commands/keystore.go @@ -55,13 +55,18 @@ type KeyRenameOutput struct { Overwrite bool } +const ( + keyStoreTypeOptionName = "type" + keyStoreSizeOptionName = "size" +) + var keyGenCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Create a new keypair", }, Options: []cmdkit.Option{ - cmdkit.StringOption("type", "t", "type of the key to create [rsa, ed25519]"), - cmdkit.IntOption("size", "s", "size of the key to generate"), + cmdkit.StringOption(keyStoreTypeOptionName, "t", "type of the key to create [rsa, ed25519]"), + cmdkit.IntOption(keyStoreSizeOptionName, "s", "size of the key to generate"), }, Arguments: []cmdkit.Argument{ cmdkit.StringArg("name", true, false, "name of key to create"), @@ -72,7 +77,7 @@ var keyGenCmd = &cmds.Command{ return err } - typ, f := req.Options["type"].(string) + typ, f := req.Options[keyStoreTypeOptionName].(string) if !f { return fmt.Errorf("please specify a key type with --type") } @@ -84,7 +89,7 @@ var keyGenCmd = &cmds.Command{ opts := []options.KeyGenerateOption{options.Key.Type(typ)} - size, sizefound := req.Options["size"].(int) + size, sizefound := req.Options[keyStoreSizeOptionName].(int) if sizefound { opts = append(opts, options.Key.Size(size)) } @@ -146,6 +151,10 @@ var keyListCmd = &cmds.Command{ Type: KeyOutputList{}, } +const ( + keyStoreForceOptionName = "force" +) + var keyRenameCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Rename a keypair", @@ -155,7 +164,7 @@ var keyRenameCmd = &cmds.Command{ cmdkit.StringArg("newName", true, false, "new name of the key"), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("force", "f", "Allow to overwrite an existing key."), + cmdkit.BoolOption(keyStoreForceOptionName, "f", "Allow to overwrite an existing key."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env) @@ -165,7 +174,7 @@ var keyRenameCmd = &cmds.Command{ name := req.Arguments[0] newName := req.Arguments[1] - force, _ := req.Options["force"].(bool) + force, _ := req.Options[keyStoreForceOptionName].(bool) key, overwritten, err := api.Key().Rename(req.Context, name, newName, options.Key.Force(force)) if err != nil { diff --git a/core/commands/log.go b/core/commands/log.go index 028061d13..b4be7354e 100644 --- a/core/commands/log.go +++ b/core/commands/log.go @@ -1,10 +1,12 @@ package commands import ( + "bytes" "fmt" "io" cmds "github.com/ipfs/go-ipfs/commands" + e "github.com/ipfs/go-ipfs/core/commands/e" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" @@ -110,3 +112,23 @@ Outputs event log messages (not other log messages) as they are generated. res.SetOutput(r) }, } + +func stringListMarshaler(res cmds.Response) (io.Reader, error) { + v, err := unwrapOutput(res.Output()) + if err != nil { + return nil, err + } + + list, ok := v.(*stringList) + if !ok { + return nil, e.TypeErr(list, v) + } + + buf := new(bytes.Buffer) + for _, s := range list.Strings { + buf.WriteString(s) + buf.WriteString("\n") + } + + return buf, nil +} diff --git a/core/commands/ls.go b/core/commands/ls.go index 491ab671a..5981d0360 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -7,19 +7,17 @@ import ( "text/tabwriter" cmds "github.com/ipfs/go-ipfs/commands" - core "github.com/ipfs/go-ipfs/core" e "github.com/ipfs/go-ipfs/core/commands/e" - unixfs "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - unixfspb "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/pb" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - blockservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + iface "github.com/ipfs/go-ipfs/core/coreapi/interface" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" + unixfs "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + unixfspb "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/pb" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + blockservice "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -38,6 +36,11 @@ type LsOutput struct { Objects []LsObject } +const ( + lsHeadersOptionNameTime = "headers" + lsResolveTypeOptionName = "resolve-type" +) + var LsCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List directory contents for Unix filesystem objects.", @@ -55,8 +58,8 @@ The JSON output contains type information. cmdkit.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("headers", "v", "Print table headers (Hash, Size, Name)."), - cmdkit.BoolOption("resolve-type", "Resolve linked objects to find out their types.").WithDefault(true), + cmdkit.BoolOption(lsHeadersOptionNameTime, "v", "Print table headers (Hash, Size, Name)."), + cmdkit.BoolOption(lsResolveTypeOptionName, "Resolve linked objects to find out their types.").WithDefault(true), }, Run: func(req cmds.Request, res cmds.Response) { nd, err := req.InvocContext().GetNode() @@ -65,13 +68,19 @@ The JSON output contains type information. return } - // get options early -> exit early in case of error - if _, _, err := req.Option("headers").Bool(); err != nil { + api, err := req.InvocContext().GetApi() + if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - resolve, _, err := req.Option("resolve-type").Bool() + // get options early -> exit early in case of error + if _, _, err := req.Option(lsHeadersOptionNameTime).Bool(); err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + + resolve, _, err := req.Option(lsResolveTypeOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -88,18 +97,13 @@ The JSON output contains type information. var dagnodes []ipld.Node for _, fpath := range paths { - p, err := path.ParsePath(fpath) + p, err := iface.ParsePath(fpath) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - r := &resolver.Resolver{ - DAG: nd.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - - dagnode, err := core.Resolve(req.Context(), nd.Namesys, r, p) + dagnode, err := api.ResolveNode(req.Context(), p) if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -108,9 +112,11 @@ The JSON output contains type information. } output := make([]LsObject, len(req.Arguments())) + ng := merkledag.NewSession(req.Context(), nd.DAG) + ro := merkledag.NewReadOnlyDagService(ng) for i, dagnode := range dagnodes { - dir, err := uio.NewDirectoryFromNode(nd.DAG, dagnode) + dir, err := uio.NewDirectoryFromNode(ro, dagnode) if err != nil && err != uio.ErrNotADir { res.SetError(fmt.Errorf("the data in %s (at %q) is not a UnixFS directory: %s", dagnode.Cid(), paths[i], err), cmdkit.ErrNormal) return @@ -177,7 +183,7 @@ The JSON output contains type information. return nil, err } - headers, _, _ := res.Request().Option("headers").Bool() + headers, _, _ := res.Request().Option(lsHeadersOptionNameTime).Bool() output, ok := v.(*LsOutput) if !ok { return nil, e.TypeErr(output, v) diff --git a/core/commands/mount_unix.go b/core/commands/mount_unix.go index 72d300f5b..2101fb87b 100644 --- a/core/commands/mount_unix.go +++ b/core/commands/mount_unix.go @@ -12,7 +12,7 @@ import ( nodeMount "github.com/ipfs/go-ipfs/fuse/node" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) var MountCmd = &cmds.Command{ diff --git a/core/commands/name/ipns.go b/core/commands/name/ipns.go index 9ee2e8c5c..dc5cef311 100644 --- a/core/commands/name/ipns.go +++ b/core/commands/name/ipns.go @@ -9,14 +9,13 @@ import ( cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" e "github.com/ipfs/go-ipfs/core/commands/e" - namesys "github.com/ipfs/go-ipfs/namesys" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" nsopts "github.com/ipfs/go-ipfs/namesys/opts" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - offline "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) var log = logging.Logger("core/commands/ipns") @@ -82,44 +81,21 @@ Resolve the value of a dnslink: cmdkit.BoolOption(streamOptionName, "s", "Stream entries as they are found."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - if !n.OnlineMode() { - err := n.SetupOfflineRouting() - if err != nil { - return err - } - } - nocache, _ := req.Options["nocache"].(bool) local, _ := req.Options["local"].(bool) - // default to nodes namesys resolver - var resolver namesys.Resolver = n.Namesys - - if local && nocache { - return errors.New("cannot specify both local and nocache") - } - - if local { - offroute := offline.NewOfflineRouter(n.Repo.Datastore(), n.RecordValidator) - resolver = namesys.NewIpnsResolver(offroute) - } - - if nocache { - resolver = namesys.NewNameSystem(n.Routing, n.Repo.Datastore(), 0) - } - var name string if len(req.Arguments) == 0 { - if n.Identity == "" { - return errors.New("identity not loaded") + self, err := api.Key().Self(req.Context) + if err != nil { + return err } - name = n.Identity.Pretty() - + name = self.ID().Pretty() } else { name = req.Arguments[0] } @@ -128,12 +104,17 @@ Resolve the value of a dnslink: rc, rcok := req.Options[dhtRecordCountOptionName].(int) dhtt, dhttok := req.Options[dhtTimeoutOptionName].(string) stream, _ := req.Options[streamOptionName].(bool) - var ropts []nsopts.ResolveOpt + + opts := []options.NameResolveOption{ + options.Name.Local(local), + options.Name.Cache(!nocache), + } + if !recursive { - ropts = append(ropts, nsopts.Depth(1)) + opts = append(opts, options.Name.ResolveOption(nsopts.Depth(1))) } if rcok { - ropts = append(ropts, nsopts.DhtRecordCount(uint(rc))) + opts = append(opts, options.Name.ResolveOption(nsopts.DhtRecordCount(uint(rc)))) } if dhttok { d, err := time.ParseDuration(dhtt) @@ -143,34 +124,37 @@ Resolve the value of a dnslink: if d < 0 { return errors.New("DHT timeout value must be >= 0") } - ropts = append(ropts, nsopts.DhtTimeout(d)) + opts = append(opts, options.Name.ResolveOption(nsopts.DhtTimeout(d))) } if !strings.HasPrefix(name, "/ipns/") { name = "/ipns/" + name } - // TODO: better errors (in the case of not finding the name, we get "failed to find any peer in table") - if !stream { - output, err := resolver.Resolve(req.Context, name, ropts...) + output, err := api.Name().Resolve(req.Context, name, opts...) if err != nil { return err } - return cmds.EmitOnce(res, &ResolvedPath{output}) + return cmds.EmitOnce(res, &ResolvedPath{path.FromString(output.String())}) + } + + output, err := api.Name().Search(req.Context, name, opts...) + if err != nil { + return err } - output := resolver.ResolveAsync(req.Context, name, ropts...) for v := range output { if v.Err != nil { return err } - if err := res.Emit(&ResolvedPath{v.Path}); err != nil { + if err := res.Emit(&ResolvedPath{path.FromString(v.Path.String())}); err != nil { return err } } + return nil }, Encoders: cmds.EncoderMap{ diff --git a/core/commands/name/publish.go b/core/commands/name/publish.go index f34bbbbc3..1d0688373 100644 --- a/core/commands/name/publish.go +++ b/core/commands/name/publish.go @@ -1,28 +1,22 @@ package name import ( - "context" "errors" "fmt" "io" "time" - core "github.com/ipfs/go-ipfs/core" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" e "github.com/ipfs/go-ipfs/core/commands/e" - keystore "github.com/ipfs/go-ipfs/keystore" + iface "github.com/ipfs/go-ipfs/core/coreapi/interface" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" - crypto "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) var ( errAllowOffline = errors.New("can't publish while offline: pass `--allow-offline` to override") - errIpnsMount = errors.New("cannot manually publish while IPNS is mounted") - errIdentityLoad = errors.New("identity not loaded") ) const ( @@ -90,71 +84,59 @@ Alternatively, publish an using a valid PeerID (as listed by cmdkit.BoolOption(quieterOptionName, "Q", "Write only final hash."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } allowOffline, _ := req.Options[allowOfflineOptionName].(bool) - if !n.OnlineMode() { - if !allowOffline { - return errAllowOffline - } - err := n.SetupOfflineRouting() - if err != nil { - return err - } - } + kname, _ := req.Options[keyOptionName].(string) - if n.Mounts.Ipns != nil && n.Mounts.Ipns.IsActive() { - return errIpnsMount - } - - pstr := req.Arguments[0] - - if n.Identity == "" { - return errIdentityLoad - } - - popts := new(publishOpts) - - popts.verifyExists, _ = req.Options[resolveOptionName].(bool) - - validtime, _ := req.Options[lifeTimeOptionName].(string) - d, err := time.ParseDuration(validtime) + validTimeOpt, _ := req.Options[lifeTimeOptionName].(string) + validTime, err := time.ParseDuration(validTimeOpt) if err != nil { return fmt.Errorf("error parsing lifetime option: %s", err) } - popts.pubValidTime = d + opts := []options.NamePublishOption{ + options.Name.AllowOffline(allowOffline), + options.Name.Key(kname), + options.Name.ValidTime(validTime), + } - ctx := req.Context if ttl, found := req.Options[ttlOptionName].(string); found { d, err := time.ParseDuration(ttl) if err != nil { return err } - ctx = context.WithValue(ctx, "ipns-publish-ttl", d) + opts = append(opts, options.Name.TTL(d)) } - kname, _ := req.Options[keyOptionName].(string) - k, err := keylookup(n, kname) + p, err := iface.ParsePath(req.Arguments[0]) if err != nil { return err } - pth, err := path.ParsePath(pstr) + if verifyExists, _ := req.Options[resolveOptionName].(bool); verifyExists { + _, err := api.ResolveNode(req.Context, p) + if err != nil { + return err + } + } + + out, err := api.Name().Publish(req.Context, p, opts...) if err != nil { + if err == iface.ErrOffline { + err = errAllowOffline + } return err } - output, err := publish(ctx, n, k, pth, popts) - if err != nil { - return err - } - - return cmds.EmitOnce(res, output) + return cmds.EmitOnce(res, &IpnsEntry{ + Name: out.Name(), + Value: out.Value().String(), + }) }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { @@ -175,72 +157,3 @@ Alternatively, publish an using a valid PeerID (as listed by }, Type: IpnsEntry{}, } - -type publishOpts struct { - verifyExists bool - pubValidTime time.Duration -} - -func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.Path, opts *publishOpts) (*IpnsEntry, error) { - - if opts.verifyExists { - // verify the path exists - _, err := core.Resolve(ctx, n.Namesys, n.Resolver, ref) - if err != nil { - return nil, err - } - } - - eol := time.Now().Add(opts.pubValidTime) - err := n.Namesys.PublishWithEOL(ctx, k, ref, eol) - if err != nil { - return nil, err - } - - pid, err := peer.IDFromPrivateKey(k) - if err != nil { - return nil, err - } - - return &IpnsEntry{ - Name: pid.Pretty(), - Value: ref.String(), - }, nil -} - -func keylookup(n *core.IpfsNode, k string) (crypto.PrivKey, error) { - - res, err := n.GetKey(k) - if res != nil { - return res, nil - } - - if err != nil && err != keystore.ErrNoSuchKey { - return nil, err - } - - keys, err := n.Repo.Keystore().List() - if err != nil { - return nil, err - } - - for _, key := range keys { - privKey, err := n.Repo.Keystore().Get(key) - if err != nil { - return nil, err - } - - pubKey := privKey.GetPublic() - - pid, err := peer.IDFromPublicKey(pubKey) - if err != nil { - return nil, err - } - - if pid.Pretty() == k { - return privKey, nil - } - } - - return nil, fmt.Errorf("no key by the given name or PeerID was found") -} diff --git a/core/commands/object/object.go b/core/commands/object/object.go index 16690cdbf..bb416c7ea 100644 --- a/core/commands/object/object.go +++ b/core/commands/object/object.go @@ -19,7 +19,7 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) diff --git a/core/commands/p2p.go b/core/commands/p2p.go index 0877bd44b..5856e441a 100644 --- a/core/commands/p2p.go +++ b/core/commands/p2p.go @@ -9,16 +9,18 @@ import ( "strconv" "strings" "text/tabwriter" + "time" cmds "github.com/ipfs/go-ipfs/commands" core "github.com/ipfs/go-ipfs/core" p2p "github.com/ipfs/go-ipfs/p2p" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - "gx/ipfs/QmSzdvo9aPzLj4HXWTcgGAp8N84tZc8LbLmFZFwUb1dpWk/go-ipfs-addr" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + "gx/ipfs/QmesXvbRGyKQn1XbPHx1Mr5E6RTJYR9c8zwFVuGZq9Aa1j/go-ipfs-addr" + madns "gx/ipfs/QmfXU2MhWoegxHoeMd3A2ytL2P6CY4FfqGWc23LTNWBwZt/go-multiaddr-dns" ) // P2PProtoPrefix is the default required prefix for protocol names @@ -49,6 +51,12 @@ type P2PStreamsOutput struct { Streams []P2PStreamInfoOutput } +const ( + allowCustomProtocolOptionName = "allow-custom-protocol" +) + +var resolveTimeout = 10 * time.Second + // P2PCmd is the 'ipfs p2p' command var P2PCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ @@ -91,7 +99,7 @@ Example: cmdkit.StringArg("target-address", true, false, "Target endpoint."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("allow-custom-protocol", "Don't require /x/ prefix"), + cmdkit.BoolOption(allowCustomProtocolOptionName, "Don't require /x/ prefix"), }, Run: func(req cmds.Request, res cmds.Response) { n, err := p2pGetNode(req) @@ -112,13 +120,13 @@ Example: return } - target, err := ipfsaddr.ParseString(targetOpt) + targets, err := parseIpfsAddr(targetOpt) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - allowCustom, _, err := req.Option("allow-custom-protocol").Bool() + allowCustom, _, err := req.Option(allowCustomProtocolOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -129,7 +137,7 @@ Example: return } - if err := forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, target); err != nil { + if err := forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, targets); err != nil { res.SetError(err, cmdkit.ErrNormal) return } @@ -137,6 +145,37 @@ Example: }, } +// parseIpfsAddr is a function that takes in addr string and return ipfsAddrs +func parseIpfsAddr(addr string) ([]ipfsaddr.IPFSAddr, error) { + mutiladdr, err := ma.NewMultiaddr(addr) + if err != nil { + return nil, err + } + if _, err := mutiladdr.ValueForProtocol(ma.P_IPFS); err == nil { + iaddrs := make([]ipfsaddr.IPFSAddr, 1) + iaddrs[0], err = ipfsaddr.ParseMultiaddr(mutiladdr) + if err != nil { + return nil, err + } + return iaddrs, nil + } + // resolve mutiladdr whose protocol is not ma.P_IPFS + ctx, cancel := context.WithTimeout(context.Background(), resolveTimeout) + addrs, err := madns.Resolve(ctx, mutiladdr) + cancel() + if len(addrs) == 0 { + return nil, errors.New("fail to resolve the multiaddr:" + mutiladdr.String()) + } + iaddrs := make([]ipfsaddr.IPFSAddr, len(addrs)) + for i, addr := range addrs { + iaddrs[i], err = ipfsaddr.ParseMultiaddr(addr) + if err != nil { + return nil, err + } + } + return iaddrs, nil +} + var p2pListenCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Create libp2p service", @@ -156,7 +195,7 @@ Example: cmdkit.StringArg("target-address", true, false, "Target endpoint."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("allow-custom-protocol", "Don't require /x/ prefix"), + cmdkit.BoolOption(allowCustomProtocolOptionName, "Don't require /x/ prefix"), }, Run: func(req cmds.Request, res cmds.Response) { n, err := p2pGetNode(req) @@ -176,7 +215,7 @@ Example: return } - allowCustom, _, err := req.Option("allow-custom-protocol").Bool() + allowCustom, _, err := req.Option(allowCustomProtocolOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -204,22 +243,27 @@ func forwardRemote(ctx context.Context, p *p2p.P2P, proto protocol.ID, target ma } // forwardLocal forwards local connections to a libp2p service -func forwardLocal(ctx context.Context, p *p2p.P2P, ps pstore.Peerstore, proto protocol.ID, bindAddr ma.Multiaddr, addr ipfsaddr.IPFSAddr) error { - if addr != nil { +func forwardLocal(ctx context.Context, p *p2p.P2P, ps pstore.Peerstore, proto protocol.ID, bindAddr ma.Multiaddr, addrs []ipfsaddr.IPFSAddr) error { + for _, addr := range addrs { ps.AddAddr(addr.ID(), addr.Multiaddr(), pstore.TempAddrTTL) } - // TODO: return some info - _, err := p.ForwardLocal(ctx, addr.ID(), proto, bindAddr) + // the length of the addrs must large than 0 + // peerIDs in addr must be the same and choose addr[0] to connect + _, err := p.ForwardLocal(ctx, addrs[0].ID(), proto, bindAddr) return err } +const ( + p2pHeadersOptionName = "headers" +) + var p2pLsCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List active p2p listeners.", }, Options: []cmdkit.Option{ - cmdkit.BoolOption("headers", "v", "Print table headers (Protocol, Listen, Target)."), + cmdkit.BoolOption(p2pHeadersOptionName, "v", "Print table headers (Protocol, Listen, Target)."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := p2pGetNode(req) @@ -260,7 +304,7 @@ var p2pLsCmd = &cmds.Command{ return nil, err } - headers, _, _ := res.Request().Option("headers").Bool() + headers, _, _ := res.Request().Option(p2pHeadersOptionName).Bool() list := v.(*P2PLsOutput) buf := new(bytes.Buffer) w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) @@ -278,15 +322,22 @@ var p2pLsCmd = &cmds.Command{ }, } +const ( + p2pAllOptionName = "all" + p2pProtocolOptionName = "protocol" + p2pListenAddressOptionName = "listen-address" + p2pTargetAddressOptionName = "target-address" +) + var p2pCloseCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Stop listening for new connections to forward.", }, Options: []cmdkit.Option{ - cmdkit.BoolOption("all", "a", "Close all listeners."), - cmdkit.StringOption("protocol", "p", "Match protocol name"), - cmdkit.StringOption("listen-address", "l", "Match listen address"), - cmdkit.StringOption("target-address", "t", "Match target address"), + cmdkit.BoolOption(p2pAllOptionName, "a", "Close all listeners."), + cmdkit.StringOption(p2pProtocolOptionName, "p", "Match protocol name"), + cmdkit.StringOption(p2pListenAddressOptionName, "l", "Match listen address"), + cmdkit.StringOption(p2pTargetAddressOptionName, "t", "Match target address"), }, Run: func(req cmds.Request, res cmds.Response) { n, err := p2pGetNode(req) @@ -295,10 +346,10 @@ var p2pCloseCmd = &cmds.Command{ return } - closeAll, _, _ := req.Option("all").Bool() - protoOpt, p, _ := req.Option("protocol").String() - listenOpt, l, _ := req.Option("listen-address").String() - targetOpt, t, _ := req.Option("target-address").String() + closeAll, _, _ := req.Option(p2pAllOptionName).Bool() + protoOpt, p, _ := req.Option(p2pProtocolOptionName).String() + listenOpt, l, _ := req.Option(p2pListenAddressOptionName).String() + targetOpt, t, _ := req.Option(p2pTargetAddressOptionName).String() proto := protocol.ID(protoOpt) @@ -384,7 +435,7 @@ var p2pStreamLsCmd = &cmds.Command{ Tagline: "List active p2p streams.", }, Options: []cmdkit.Option{ - cmdkit.BoolOption("headers", "v", "Print table headers (ID, Protocol, Local, Remote)."), + cmdkit.BoolOption(p2pHeadersOptionName, "v", "Print table headers (ID, Protocol, Local, Remote)."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := p2pGetNode(req) @@ -418,7 +469,7 @@ var p2pStreamLsCmd = &cmds.Command{ return nil, err } - headers, _, _ := res.Request().Option("headers").Bool() + headers, _, _ := res.Request().Option(p2pHeadersOptionName).Bool() list := v.(*P2PStreamsOutput) buf := new(bytes.Buffer) w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) @@ -444,7 +495,7 @@ var p2pStreamCloseCmd = &cmds.Command{ cmdkit.StringArg("id", false, false, "Stream identifier"), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("all", "a", "Close all streams."), + cmdkit.BoolOption(p2pAllOptionName, "a", "Close all streams."), }, Run: func(req cmds.Request, res cmds.Response) { res.SetOutput(nil) @@ -455,7 +506,7 @@ var p2pStreamCloseCmd = &cmds.Command{ return } - closeAll, _, _ := req.Option("all").Bool() + closeAll, _, _ := req.Option(p2pAllOptionName).Bool() var handlerID uint64 if !closeAll { diff --git a/core/commands/pin.go b/core/commands/pin.go index bb6540fa5..f4a3a110e 100644 --- a/core/commands/pin.go +++ b/core/commands/pin.go @@ -10,18 +10,17 @@ import ( cmds "github.com/ipfs/go-ipfs/commands" core "github.com/ipfs/go-ipfs/core" e "github.com/ipfs/go-ipfs/core/commands/e" + iface "github.com/ipfs/go-ipfs/core/coreapi/interface" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" corerepo "github.com/ipfs/go-ipfs/core/corerepo" pin "github.com/ipfs/go-ipfs/pin" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" "gx/ipfs/QmVkMRSkXrpjqrroEXWuYBvDBnXCdMMY6gsKicBGVGUqKT/go-verifcid" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" ) var PinCmd = &cmds.Command{ @@ -47,6 +46,11 @@ type AddPinOutput struct { Progress int `json:",omitempty"` } +const ( + pinRecursiveOptionName = "recursive" + pinProgressOptionName = "progress" +) + var addPinCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Pin objects to local storage.", @@ -57,8 +61,8 @@ var addPinCmd = &cmds.Command{ cmdkit.StringArg("ipfs-path", true, true, "Path to object(s) to be pinned.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("recursive", "r", "Recursively pin the object linked to by the specified object(s).").WithDefault(true), - cmdkit.BoolOption("progress", "Show progress"), + cmdkit.BoolOption(pinRecursiveOptionName, "r", "Recursively pin the object linked to by the specified object(s).").WithDefault(true), + cmdkit.BoolOption(pinProgressOptionName, "Show progress"), }, Type: AddPinOutput{}, Run: func(req cmds.Request, res cmds.Response) { @@ -68,18 +72,24 @@ var addPinCmd = &cmds.Command{ return } - defer n.Blockstore.PinLock().Unlock() - - // set recursive flag - recursive, _, err := req.Option("recursive").Bool() + api, err := req.InvocContext().GetApi() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - showProgress, _, _ := req.Option("progress").Bool() + + defer n.Blockstore.PinLock().Unlock() + + // set recursive flag + recursive, _, err := req.Option(pinRecursiveOptionName).Bool() + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + showProgress, _, _ := req.Option(pinProgressOptionName).Bool() if !showProgress { - added, err := corerepo.Pin(n, req.Context(), req.Arguments(), recursive) + added, err := corerepo.Pin(n, api, req.Context(), req.Arguments(), recursive) if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -99,7 +109,7 @@ var addPinCmd = &cmds.Command{ } ch := make(chan pinResult, 1) go func() { - added, err := corerepo.Pin(n, ctx, req.Arguments(), recursive) + added, err := corerepo.Pin(n, api, ctx, req.Arguments(), recursive) ch <- pinResult{pins: added, err: err} }() @@ -183,7 +193,7 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.) cmdkit.StringArg("ipfs-path", true, true, "Path to object(s) to be unpinned.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("recursive", "r", "Recursively unpin the object linked to by the specified object(s).").WithDefault(true), + cmdkit.BoolOption(pinRecursiveOptionName, "r", "Recursively unpin the object linked to by the specified object(s).").WithDefault(true), }, Type: PinOutput{}, Run: func(req cmds.Request, res cmds.Response) { @@ -193,14 +203,20 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.) return } - // set recursive flag - recursive, _, err := req.Option("recursive").Bool() + api, err := req.InvocContext().GetApi() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - removed, err := corerepo.Unpin(n, req.Context(), req.Arguments(), recursive) + // set recursive flag + recursive, _, err := req.Option(pinRecursiveOptionName).Bool() + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + + removed, err := corerepo.Unpin(n, api, req.Context(), req.Arguments(), recursive) if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -229,6 +245,11 @@ collected if needed. (By default, recursively. Use -r=false for direct pins.) }, } +const ( + pinTypeOptionName = "type" + pinQuietOptionName = "quiet" +) + var listPinCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List objects pinned to local storage.", @@ -277,8 +298,8 @@ Example: cmdkit.StringArg("ipfs-path", false, true, "Path to object(s) to be listed."), }, Options: []cmdkit.Option{ - cmdkit.StringOption("type", "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"), - cmdkit.BoolOption("quiet", "q", "Write just hashes of objects."), + cmdkit.StringOption(pinTypeOptionName, "t", "The type of pinned keys to list. Can be \"direct\", \"indirect\", \"recursive\", or \"all\".").WithDefault("all"), + cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of objects."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -287,7 +308,13 @@ Example: return } - typeStr, _, err := req.Option("type").String() + api, err := req.InvocContext().GetApi() + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + + typeStr, _, err := req.Option(pinTypeOptionName).String() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -304,7 +331,7 @@ Example: var keys map[string]RefKeyObject if len(req.Arguments()) > 0 { - keys, err = pinLsKeys(req.Context(), req.Arguments(), typeStr, n) + keys, err = pinLsKeys(req.Context(), req.Arguments(), typeStr, n, api) } else { keys, err = pinLsAll(req.Context(), typeStr, n) } @@ -323,7 +350,7 @@ Example: return nil, err } - quiet, _, err := res.Request().Option("quiet").Bool() + quiet, _, err := res.Request().Option(pinQuietOptionName).Bool() if err != nil { return nil, err } @@ -345,6 +372,10 @@ Example: }, } +const ( + pinUnpinOptionName = "unpin" +) + var updatePinCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Update a recursive pin", @@ -360,58 +391,35 @@ new pin and removing the old one. cmdkit.StringArg("to-path", true, false, "Path to new object to be pinned."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("unpin", "Remove the old pin.").WithDefault(true), + cmdkit.BoolOption(pinUnpinOptionName, "Remove the old pin.").WithDefault(true), }, Type: PinOutput{}, Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() + api, err := req.InvocContext().GetApi() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - unpin, _, err := req.Option("unpin").Bool() + unpin, _, err := req.Option(pinUnpinOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - from, err := path.ParsePath(req.Arguments()[0]) + from, err := iface.ParsePath(req.Arguments()[0]) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - to, err := path.ParsePath(req.Arguments()[1]) + to, err := iface.ParsePath(req.Arguments()[1]) if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - r := &resolver.Resolver{ - DAG: n.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - - fromc, err := core.ResolveToCid(req.Context(), n.Namesys, r, from) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - - toc, err := core.ResolveToCid(req.Context(), n.Namesys, r, to) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - - err = n.Pinning.Update(req.Context(), fromc, toc, unpin) - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - - err = n.Pinning.Flush() + err = api.Pin().Update(req.Context(), from, to, options.Pin.Unpin(unpin)) if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -437,13 +445,17 @@ new pin and removing the old one. }, } +const ( + pinVerboseOptionName = "verbose" +) + var verifyPinCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Verify that recursive pins are complete.", }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "Also write the hashes of non-broken pins."), - cmdkit.BoolOption("quiet", "q", "Write just hashes of broken pins."), + cmdkit.BoolOption(pinVerboseOptionName, "Also write the hashes of non-broken pins."), + cmdkit.BoolOption(pinQuietOptionName, "q", "Write just hashes of broken pins."), }, Run: func(req cmds.Request, res cmds.Response) { n, err := req.InvocContext().GetNode() @@ -452,8 +464,8 @@ var verifyPinCmd = &cmds.Command{ return } - verbose, _, _ := res.Request().Option("verbose").Bool() - quiet, _, _ := res.Request().Option("quiet").Bool() + verbose, _, _ := res.Request().Option(pinVerboseOptionName).Bool() + quiet, _, _ := res.Request().Option(pinQuietOptionName).Bool() if verbose && quiet { res.SetError(fmt.Errorf("the --verbose and --quiet options can not be used at the same time"), cmdkit.ErrNormal) @@ -470,7 +482,7 @@ var verifyPinCmd = &cmds.Command{ Type: PinVerifyRes{}, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { - quiet, _, _ := res.Request().Option("quiet").Bool() + quiet, _, _ := res.Request().Option(pinQuietOptionName).Bool() out, err := unwrapOutput(res.Output()) if err != nil { @@ -501,7 +513,7 @@ type RefKeyList struct { Keys map[string]RefKeyObject } -func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode) (map[string]RefKeyObject, error) { +func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsNode, api iface.CoreAPI) (map[string]RefKeyObject, error) { mode, ok := pin.StringToMode(typeStr) if !ok { @@ -510,23 +522,18 @@ func pinLsKeys(ctx context.Context, args []string, typeStr string, n *core.IpfsN keys := make(map[string]RefKeyObject) - r := &resolver.Resolver{ - DAG: n.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - for _, p := range args { - pth, err := path.ParsePath(p) + pth, err := iface.ParsePath(p) if err != nil { return nil, err } - c, err := core.ResolveToCid(ctx, n.Namesys, r, pth) + c, err := api.ResolvePath(ctx, pth) if err != nil { return nil, err } - pinType, pinned, err := n.Pinning.IsPinnedWithType(c, mode) + pinType, pinned, err := n.Pinning.IsPinnedWithType(c.Cid(), mode) if err != nil { return nil, err } diff --git a/core/commands/ping.go b/core/commands/ping.go index e745525f4..7807f35c7 100644 --- a/core/commands/ping.go +++ b/core/commands/ping.go @@ -14,9 +14,9 @@ import ( u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) const kPingTimeout = 10 * time.Second @@ -27,6 +27,10 @@ type PingResult struct { Text string } +const ( + pingCountOptionName = "count" +) + // ErrPingSelf is returned when the user attempts to ping themself. var ErrPingSelf = errors.New("error: can't ping self") @@ -43,7 +47,7 @@ trip latency information. cmdkit.StringArg("peer ID", true, true, "ID of peer to be pinged.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.IntOption("count", "n", "Number of ping messages to send.").WithDefault(10), + cmdkit.IntOption(pingCountOptionName, "n", "Number of ping messages to send.").WithDefault(10), }, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { @@ -97,7 +101,7 @@ trip latency information. n.Peerstore.AddAddr(peerID, addr, pstore.TempAddrTTL) // temporary } - numPings, _, err := req.Option("count").Int() + numPings, _, err := req.Option(pingCountOptionName).Int() if err != nil { res.SetError(err, cmdkit.ErrNormal) return diff --git a/core/commands/pubsub.go b/core/commands/pubsub.go index c9a723a85..e125a693b 100644 --- a/core/commands/pubsub.go +++ b/core/commands/pubsub.go @@ -3,24 +3,17 @@ package commands import ( "context" "encoding/binary" - "errors" "fmt" "io" "net/http" "sort" - "sync" - "time" - core "github.com/ipfs/go-ipfs/core" cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" e "github.com/ipfs/go-ipfs/core/commands/e" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" - cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - floodsub "gx/ipfs/QmPbYVFhKxamZAN9MyrQMDeoGYa6zkQkhAPguwFfzxPM1J/go-libp2p-floodsub" - blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) var PubsubCmd = &cmds.Command{ @@ -44,6 +37,17 @@ To use, the daemon must be run with '--enable-pubsub-experiment'. }, } +const ( + pubsubDiscoverOptionName = "discover" +) + +type pubsubMessage struct { + From []byte `json:"from,omitempty"` + Data []byte `json:"data,omitempty"` + Seqno []byte `json:"seqno,omitempty"` + TopicIDs []string `json:"topicIDs,omitempty"` +} + var PubsubSubCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Subscribe to messages on a given topic.", @@ -72,43 +76,22 @@ This command outputs data in the following encodings: cmdkit.StringArg("topic", true, false, "String name of topic to subscribe to."), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("discover", "try to discover other peers subscribed to the same topic"), + cmdkit.BoolOption(pubsubDiscoverOptionName, "try to discover other peers subscribed to the same topic"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - // Must be online! - if !n.OnlineMode() { - return cmdkit.Errorf(cmdkit.ErrClient, ErrNotOnline.Error()) - } - - if n.Floodsub == nil { - return fmt.Errorf("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use") - } - topic := req.Arguments[0] - sub, err := n.Floodsub.Subscribe(topic) + discover, _ := req.Options[pubsubDiscoverOptionName].(bool) + + sub, err := api.PubSub().Subscribe(req.Context, topic, options.PubSub.Discover(discover)) if err != nil { return err } - defer sub.Cancel() - - discover, _ := req.Options["discover"].(bool) - if discover { - go func() { - blk := blocks.NewBlock([]byte("floodsub:" + topic)) - err := n.Blocks.AddBlock(blk) - if err != nil { - log.Error("pubsub discovery: ", err) - return - } - - connectToPubSubPeers(req.Context, n, blk.Cid()) - }() - } + defer sub.Close() if f, ok := res.(http.Flusher); ok { f.Flush() @@ -122,15 +105,17 @@ This command outputs data in the following encodings: return err } - err = res.Emit(msg) - if err != nil { - return err - } + res.Emit(&pubsubMessage{ + Data: msg.Data(), + From: []byte(msg.From()), + Seqno: msg.Seq(), + TopicIDs: msg.Topics(), + }) } }, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { - m, ok := v.(*floodsub.Message) + m, ok := v.(*pubsubMessage) if !ok { return fmt.Errorf("unexpected type: %T", v) } @@ -139,7 +124,7 @@ This command outputs data in the following encodings: return err }), "ndpayload": cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { - m, ok := v.(*floodsub.Message) + m, ok := v.(*pubsubMessage) if !ok { return fmt.Errorf("unexpected type: %T", v) } @@ -149,7 +134,7 @@ This command outputs data in the following encodings: return err }), "lenpayload": cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { - m, ok := v.(*floodsub.Message) + m, ok := v.(*pubsubMessage) if !ok { return fmt.Errorf("unexpected type: %T", v) } @@ -162,31 +147,7 @@ This command outputs data in the following encodings: return err }), }, - Type: floodsub.Message{}, -} - -func connectToPubSubPeers(ctx context.Context, n *core.IpfsNode, cid cid.Cid) { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - provs := n.Routing.FindProvidersAsync(ctx, cid, 10) - wg := &sync.WaitGroup{} - for p := range provs { - wg.Add(1) - go func(pi pstore.PeerInfo) { - defer wg.Done() - ctx, cancel := context.WithTimeout(ctx, time.Second*10) - defer cancel() - err := n.PeerHost.Connect(ctx, pi) - if err != nil { - log.Info("pubsub discover: ", err) - return - } - log.Info("connected to pubsub peer:", pi.ID) - }(p) - } - - wg.Wait() + Type: pubsubMessage{}, } var PubsubPubCmd = &cmds.Command{ @@ -206,20 +167,11 @@ To use, the daemon must be run with '--enable-pubsub-experiment'. cmdkit.StringArg("data", true, true, "Payload of message to publish.").EnableStdin(), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - // Must be online! - if !n.OnlineMode() { - return cmdkit.Errorf(cmdkit.ErrClient, ErrNotOnline.Error()) - } - - if n.Floodsub == nil { - return errors.New("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use.") - } - topic := req.Arguments[0] err = req.ParseBodyArgs() @@ -228,7 +180,7 @@ To use, the daemon must be run with '--enable-pubsub-experiment'. } for _, data := range req.Arguments[1:] { - if err := n.Floodsub.Publish(topic, []byte(data)); err != nil { + if err := api.PubSub().Publish(req.Context, topic, []byte(data)); err != nil { return err } } @@ -250,21 +202,17 @@ To use, the daemon must be run with '--enable-pubsub-experiment'. `, }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - // Must be online! - if !n.OnlineMode() { - return cmdkit.Errorf(cmdkit.ErrClient, ErrNotOnline.Error()) + l, err := api.PubSub().Ls(req.Context) + if err != nil { + return err } - if n.Floodsub == nil { - return errors.New("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use.") - } - - return cmds.EmitOnce(res, stringList{n.Floodsub.GetTopics()}) + return cmds.EmitOnce(res, stringList{l}) }, Type: stringList{}, Encoders: cmds.EncoderMap{ @@ -304,26 +252,21 @@ To use, the daemon must be run with '--enable-pubsub-experiment'. cmdkit.StringArg("topic", false, false, "topic to list connected peers of"), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env) if err != nil { return err } - // Must be online! - if !n.OnlineMode() { - return cmdkit.Errorf(cmdkit.ErrClient, ErrNotOnline.Error()) - } - - if n.Floodsub == nil { - return errors.New("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use") - } - var topic string if len(req.Arguments) == 1 { topic = req.Arguments[0] } - peers := n.Floodsub.ListPeers(topic) + peers, err := api.PubSub().Peers(req.Context, options.PubSub.Topic(topic)) + if err != nil { + return err + } + list := &stringList{make([]string, 0, len(peers))} for _, peer := range peers { diff --git a/core/commands/refs.go b/core/commands/refs.go index c28af5317..2ef9a517f 100644 --- a/core/commands/refs.go +++ b/core/commands/refs.go @@ -12,8 +12,8 @@ import ( e "github.com/ipfs/go-ipfs/core/commands/e" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -22,6 +22,14 @@ type KeyList struct { Keys []cid.Cid } +const ( + refsFormatOptionName = "format" + refsEdgesOptionName = "edges" + refsUniqueOptionName = "unique" + refsRecursiveOptionName = "recursive" + refsMaxDepthOptionName = "max-depth" +) + // KeyListTextMarshaler outputs a KeyList as plaintext, one key per line func KeyListTextMarshaler(res cmds.Response) (io.Reader, error) { out, err := unwrapOutput(res.Output()) @@ -60,11 +68,11 @@ NOTE: List all references recursively by using the flag '-r'. cmdkit.StringArg("ipfs-path", true, true, "Path to the object(s) to list refs from.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.StringOption("format", "Emit edges with given format. Available tokens: .").WithDefault(""), - cmdkit.BoolOption("edges", "e", "Emit edge format: ` -> `."), - cmdkit.BoolOption("unique", "u", "Omit duplicate refs from output."), - cmdkit.BoolOption("recursive", "r", "Recursively list links of child nodes."), - cmdkit.IntOption("max-depth", "Only for recursive refs, limits fetch and listing to the given depth").WithDefault(-1), + cmdkit.StringOption(refsFormatOptionName, "Emit edges with given format. Available tokens: .").WithDefault(""), + cmdkit.BoolOption(refsEdgesOptionName, "e", "Emit edge format: ` -> `."), + cmdkit.BoolOption(refsUniqueOptionName, "u", "Omit duplicate refs from output."), + cmdkit.BoolOption(refsRecursiveOptionName, "r", "Recursively list links of child nodes."), + cmdkit.IntOption(refsMaxDepthOptionName, "Only for recursive refs, limits fetch and listing to the given depth").WithDefault(-1), }, Run: func(req cmds.Request, res cmds.Response) { ctx := req.Context() @@ -74,19 +82,19 @@ NOTE: List all references recursively by using the flag '-r'. return } - unique, _, err := req.Option("unique").Bool() + unique, _, err := req.Option(refsUniqueOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - recursive, _, err := req.Option("recursive").Bool() + recursive, _, err := req.Option(refsRecursiveOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - maxDepth, _, err := req.Option("max-depth").Int() + maxDepth, _, err := req.Option(refsMaxDepthOptionName).Int() if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -96,13 +104,13 @@ NOTE: List all references recursively by using the flag '-r'. maxDepth = 1 // write only direct refs } - format, _, err := req.Option("format").String() + format, _, err := req.Option(refsFormatOptionName).String() if err != nil { res.SetError(err, cmdkit.ErrNormal) return } - edges, _, err := req.Option("edges").Bool() + edges, _, err := req.Option(refsEdgesOptionName).Bool() if err != nil { res.SetError(err, cmdkit.ErrNormal) return diff --git a/core/commands/repo.go b/core/commands/repo.go index 2e4480df8..0f13f5606 100644 --- a/core/commands/repo.go +++ b/core/commands/repo.go @@ -19,9 +19,9 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) type RepoVersion struct { @@ -51,6 +51,11 @@ type GcResult struct { Error string `json:",omitempty"` } +const ( + repoStreamErrorsOptionName = "stream-errors" + repoQuietOptionName = "quiet" +) + var repoGcCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Perform a garbage collection sweep on the repo.", @@ -61,8 +66,8 @@ order to reclaim hard disk space. `, }, Options: []cmdkit.Option{ - cmdkit.BoolOption("stream-errors", "Stream errors."), - cmdkit.BoolOption("quiet", "q", "Write minimal output."), + cmdkit.BoolOption(repoStreamErrorsOptionName, "Stream errors."), + cmdkit.BoolOption(repoQuietOptionName, "q", "Write minimal output."), }, Run: func(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) @@ -70,7 +75,7 @@ order to reclaim hard disk space. return err } - streamErrors, _ := req.Options["stream-errors"].(bool) + streamErrors, _ := req.Options[repoStreamErrorsOptionName].(bool) gcOutChan := corerepo.GarbageCollectAsync(n, req.Context) @@ -101,7 +106,7 @@ order to reclaim hard disk space. Type: GcResult{}, Encoders: cmds.EncoderMap{ cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { - quiet, _ := req.Options["quiet"].(bool) + quiet, _ := req.Options[repoQuietOptionName].(bool) obj, ok := v.(*GcResult) if !ok { @@ -124,6 +129,11 @@ order to reclaim hard disk space. }, } +const ( + repoSizeOnlyOptionName = "size-only" + repoHumanOptionName = "human" +) + var repoStatCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Get stats for the currently used repo.", @@ -139,8 +149,8 @@ Version string The repo version. `, }, Options: []cmdkit.Option{ - cmdkit.BoolOption("size-only", "Only report RepoSize and StorageMax."), - cmdkit.BoolOption("human", "Output sizes in MiB."), + cmdkit.BoolOption(repoSizeOnlyOptionName, "Only report RepoSize and StorageMax."), + cmdkit.BoolOption(repoHumanOptionName, "Output sizes in MiB."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { n, err := cmdenv.GetNode(env) @@ -148,7 +158,7 @@ Version string The repo version. return err } - sizeOnly, _ := req.Options["size-only"].(bool) + sizeOnly, _ := req.Options[repoSizeOnlyOptionName].(bool) if sizeOnly { sizeStat, err := corerepo.RepoSize(req.Context, n) if err != nil { @@ -178,8 +188,8 @@ Version string The repo version. wtr := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0) defer wtr.Flush() - human, _ := req.Options["human"].(bool) - sizeOnly, _ := req.Options["size-only"].(bool) + human, _ := req.Options[repoHumanOptionName].(bool) + sizeOnly, _ := req.Options[repoSizeOnlyOptionName].(bool) printSize := func(name string, size uint64) { sizeInMiB := size / (1024 * 1024) @@ -360,7 +370,7 @@ var repoVersionCmd = &oldcmds.Command{ }, Options: []cmdkit.Option{ - cmdkit.BoolOption("quiet", "q", "Write minimal output."), + cmdkit.BoolOption(repoQuietOptionName, "q", "Write minimal output."), }, Run: func(req oldcmds.Request, res oldcmds.Response) { res.SetOutput(&RepoVersion{ diff --git a/core/commands/resolve.go b/core/commands/resolve.go index 39963b6da..0ea7676ec 100644 --- a/core/commands/resolve.go +++ b/core/commands/resolve.go @@ -14,12 +14,18 @@ import ( options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" ns "github.com/ipfs/go-ipfs/namesys" nsopts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ) +const ( + resolveRecursiveOptionName = "recursive" + resolveDhtRecordCountOptionName = "dht-record-count" + resolveDhtTimeoutOptionName = "dht-timeout" +) + var ResolveCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Resolve the value of names to IPFS.", @@ -64,9 +70,9 @@ Resolve the value of an IPFS DAG path: cmdkit.StringArg("name", true, false, "The name to resolve.").EnableStdin(), }, Options: []cmdkit.Option{ - cmdkit.BoolOption("recursive", "r", "Resolve until the result is an IPFS name."), - cmdkit.IntOption("dht-record-count", "dhtrc", "Number of records to request for DHT resolution."), - cmdkit.StringOption("dht-timeout", "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."), + cmdkit.BoolOption(resolveRecursiveOptionName, "r", "Resolve until the result is an IPFS name."), + cmdkit.IntOption(resolveDhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."), + cmdkit.StringOption(resolveDhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { api, err := cmdenv.GetApi(env) @@ -87,12 +93,12 @@ Resolve the value of an IPFS DAG path: } name := req.Arguments[0] - recursive, _ := req.Options["recursive"].(bool) + recursive, _ := req.Options[resolveRecursiveOptionName].(bool) // the case when ipns is resolved step by step if strings.HasPrefix(name, "/ipns/") && !recursive { - rc, rcok := req.Options["dht-record-count"].(uint) - dhtt, dhttok := req.Options["dht-timeout"].(string) + rc, rcok := req.Options[resolveDhtRecordCountOptionName].(uint) + dhtt, dhttok := req.Options[resolveDhtTimeoutOptionName].(string) ropts := []options.NameResolveOption{ options.Name.ResolveOption(nsopts.Depth(1)), } diff --git a/core/commands/root.go b/core/commands/root.go index 0268136f6..4c53c1226 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -71,6 +71,7 @@ TOOL COMMANDS version Show ipfs version information update Download and apply go-ipfs updates commands List all available commands + cid Convert and discover properties of CIDs Use 'ipfs --help' to learn more about each command. @@ -136,13 +137,14 @@ var rootSubcommands = map[string]*cmds.Command{ "p2p": lgc.NewCommand(P2PCmd), "refs": lgc.NewCommand(RefsCmd), "resolve": ResolveCmd, - "swarm": lgc.NewCommand(SwarmCmd), + "swarm": SwarmCmd, "tar": lgc.NewCommand(TarCmd), "file": lgc.NewCommand(unixfs.UnixFSCmd), "update": lgc.NewCommand(ExternalBinary()), "urlstore": urlStoreCmd, "version": lgc.NewCommand(VersionCmd), "shutdown": daemonShutdownCmd, + "cid": CidCmd, } // RootRO is the readonly version of Root diff --git a/core/commands/stat.go b/core/commands/stat.go index 7e44af35f..a1081bd54 100644 --- a/core/commands/stat.go +++ b/core/commands/stat.go @@ -33,6 +33,13 @@ for your IPFS node.`, }, } +const ( + statPeerOptionName = "peer" + statProtoOptionName = "proto" + statPollOptionName = "poll" + statIntervalOptionName = "interval" +) + var statBwCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Print ipfs bandwidth information.", @@ -71,10 +78,10 @@ Example: `, }, Options: []cmdkit.Option{ - cmdkit.StringOption("peer", "p", "Specify a peer to print bandwidth for."), - cmdkit.StringOption("proto", "t", "Specify a protocol to print bandwidth for."), - cmdkit.BoolOption("poll", "Print bandwidth at an interval."), - cmdkit.StringOption("interval", "i", `Time interval to wait between updating output, if 'poll' is true. + cmdkit.StringOption(statPeerOptionName, "p", "Specify a peer to print bandwidth for."), + cmdkit.StringOption(statProtoOptionName, "t", "Specify a protocol to print bandwidth for."), + cmdkit.BoolOption(statPollOptionName, "Print bandwidth at an interval."), + cmdkit.StringOption(statIntervalOptionName, "i", `Time interval to wait between updating output, if 'poll' is true. This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are: "ns", "us" (or "µs"), "ms", "s", "m", "h".`).WithDefault("1s"), @@ -95,7 +102,7 @@ Example: return fmt.Errorf("bandwidth reporter disabled in config") } - pstr, pfound := req.Options["peer"].(string) + pstr, pfound := req.Options[statPeerOptionName].(string) tstr, tfound := req.Options["proto"].(string) if pfound && tfound { return cmdkit.Errorf(cmdkit.ErrClient, "please only specify peer OR protocol") @@ -110,13 +117,13 @@ Example: pid = checkpid } - timeS, _ := req.Options["interval"].(string) + timeS, _ := req.Options[statIntervalOptionName].(string) interval, err := time.ParseDuration(timeS) if err != nil { return err } - doPoll, _ := req.Options["poll"].(bool) + doPoll, _ := req.Options[statPollOptionName].(bool) for { if pfound { stats := nd.Reporter.GetBandwidthForPeer(pid) @@ -142,7 +149,7 @@ Example: Type: metrics.Stats{}, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error { - polling, _ := res.Request().Options["poll"].(bool) + polling, _ := res.Request().Options[statPollOptionName].(bool) if polling { fmt.Fprintln(os.Stdout, "Total Up Total Down Rate Up Rate Down") diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 685a8113b..83b664893 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -1,7 +1,6 @@ package commands import ( - "bytes" "errors" "fmt" "io" @@ -9,20 +8,22 @@ import ( "sort" "strings" - cmds "github.com/ipfs/go-ipfs/commands" - e "github.com/ipfs/go-ipfs/core/commands/e" - repo "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-ipfs/commands" + "github.com/ipfs/go-ipfs/core/commands/cmdenv" + "github.com/ipfs/go-ipfs/core/commands/e" + "github.com/ipfs/go-ipfs/repo" "github.com/ipfs/go-ipfs/repo/fsrepo" - swarm "gx/ipfs/QmPQoCVRHaGD25VffyB7DFV5qP65hFSQJdSDy75P1vYBKe/go-libp2p-swarm" mafilter "gx/ipfs/QmSMZwvs3n4GBikZ7hKzT17c3bk65FmyZo2JqtJ16swqCv/multiaddr-filter" - cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - iaddr "gx/ipfs/QmSzdvo9aPzLj4HXWTcgGAp8N84tZc8LbLmFZFwUb1dpWk/go-ipfs-addr" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + inet "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" + "gx/ipfs/Qmb55o5PuhvqwjdVLvc4VV3ouLziYc6TfwM9LC6GwBQokn/go-libp2p-swarm" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" - inet "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" + iaddr "gx/ipfs/QmesXvbRGyKQn1XbPHx1Mr5E6RTJYR9c8zwFVuGZq9Aa1j/go-ipfs-addr" ) type stringList struct { @@ -51,6 +52,13 @@ ipfs peers in the internet. }, } +const ( + swarmVerboseOptionName = "verbose" + swarmStreamsOptionName = "streams" + swarmLatencyOptionName = "latency" + swarmDirectionOptionName = "direction" +) + var swarmPeersCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "List peers with open connections.", @@ -59,54 +67,45 @@ var swarmPeersCmd = &cmds.Command{ `, }, Options: []cmdkit.Option{ - cmdkit.BoolOption("verbose", "v", "display all extra information"), - cmdkit.BoolOption("streams", "Also list information about open streams for each peer"), - cmdkit.BoolOption("latency", "Also list information about latency to each peer"), - cmdkit.BoolOption("direction", "Also list information about the direction of connection"), + cmdkit.BoolOption(swarmVerboseOptionName, "v", "display all extra information"), + cmdkit.BoolOption(swarmStreamsOptionName, "Also list information about open streams for each peer"), + cmdkit.BoolOption(swarmLatencyOptionName, "Also list information about latency to each peer"), + cmdkit.BoolOption(swarmDirectionOptionName, "Also list information about the direction of connection"), }, - Run: func(req cmds.Request, res cmds.Response) { - - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return + verbose, _ := req.Options[swarmVerboseOptionName].(bool) + latency, _ := req.Options[swarmLatencyOptionName].(bool) + streams, _ := req.Options[swarmStreamsOptionName].(bool) + direction, _ := req.Options[swarmDirectionOptionName].(bool) + + conns, err := api.Swarm().Peers(req.Context) + if err != nil { + return err } - verbose, _, _ := req.Option("verbose").Bool() - latency, _, _ := req.Option("latency").Bool() - streams, _, _ := req.Option("streams").Bool() - direction, _, _ := req.Option("direction").Bool() - - conns := n.PeerHost.Network().Conns() var out connInfos for _, c := range conns { - pid := c.RemotePeer() - addr := c.RemoteMultiaddr() ci := connInfo{ - Addr: addr.String(), - Peer: pid.Pretty(), + Addr: c.Address().String(), + Peer: c.ID().Pretty(), } - /* - // FIXME(steb): - swcon, ok := c.(*swarm.Conn) - if ok { - ci.Muxer = fmt.Sprintf("%T", swcon.StreamConn().Conn()) - } - */ - if verbose || direction { // set direction - ci.Direction = c.Stat().Direction + ci.Direction = c.Direction() } if verbose || latency { - lat := n.Peerstore.LatencyEWMA(pid) + lat, err := c.Latency() + if err != nil { + return err + } + if lat == 0 { ci.Latency = "n/a" } else { @@ -114,10 +113,13 @@ var swarmPeersCmd = &cmds.Command{ } } if verbose || streams { - strs := c.GetStreams() + strs, err := c.Streams() + if err != nil { + return err + } for _, s := range strs { - ci.Streams = append(ci.Streams, streamInfo{Protocol: string(s.Protocol())}) + ci.Streams = append(ci.Streams, streamInfo{Protocol: string(s)}) } } sort.Sort(&ci) @@ -125,50 +127,43 @@ var swarmPeersCmd = &cmds.Command{ } sort.Sort(&out) - res.SetOutput(&out) + return cmds.EmitOnce(res, &out) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: func(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { ci, ok := v.(*connInfos) if !ok { - return nil, e.TypeErr(ci, v) + return e.TypeErr(ci, v) } - buf := new(bytes.Buffer) pipfs := ma.ProtocolWithCode(ma.P_IPFS).Name for _, info := range ci.Peers { ids := fmt.Sprintf("/%s/%s", pipfs, info.Peer) if strings.HasSuffix(info.Addr, ids) { - fmt.Fprintf(buf, "%s", info.Addr) + fmt.Fprintf(w, "%s", info.Addr) } else { - fmt.Fprintf(buf, "%s%s", info.Addr, ids) + fmt.Fprintf(w, "%s%s", info.Addr, ids) } if info.Latency != "" { - fmt.Fprintf(buf, " %s", info.Latency) + fmt.Fprintf(w, " %s", info.Latency) } if info.Direction != inet.DirUnknown { - fmt.Fprintf(buf, " %s", directionString(info.Direction)) + fmt.Fprintf(w, " %s", directionString(info.Direction)) } - - fmt.Fprintln(buf) + fmt.Fprintln(w) for _, s := range info.Streams { if s.Protocol == "" { s.Protocol = "" } - fmt.Fprintf(buf, " %s\n", s.Protocol) + fmt.Fprintf(w, " %s\n", s.Protocol) } } - return buf, nil - }, + return nil + }), }, Type: connInfos{}, } @@ -237,41 +232,32 @@ var swarmAddrsCmd = &cmds.Command{ "local": swarmAddrsLocalCmd, "listen": swarmAddrsListenCmd, }, - Run: func(req cmds.Request, res cmds.Response) { - - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return + addrs, err := api.Swarm().KnownAddrs(req.Context) + if err != nil { + return err } - addrs := make(map[string][]string) - ps := n.PeerHost.Network().Peerstore() - for _, p := range ps.Peers() { + out := make(map[string][]string) + for p, paddrs := range addrs { s := p.Pretty() - for _, a := range ps.Addrs(p) { - addrs[s] = append(addrs[s], a.String()) + for _, a := range paddrs { + out[s] = append(out[s], a.String()) } - sort.Sort(sort.StringSlice(addrs[s])) } - res.SetOutput(&addrMap{Addrs: addrs}) + return cmds.EmitOnce(res, &addrMap{Addrs: out}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: func(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error { m, ok := v.(*addrMap) if !ok { - return nil, e.TypeErr(m, v) + return e.TypeErr(m, v) } // sort the ids first @@ -281,16 +267,15 @@ var swarmAddrsCmd = &cmds.Command{ } sort.Sort(sort.StringSlice(ids)) - buf := new(bytes.Buffer) for _, p := range ids { paddrs := m.Addrs[p] - buf.WriteString(fmt.Sprintf("%s (%d)\n", p, len(paddrs))) + fmt.Fprintf(w, "%s (%d)\n", p, len(paddrs)) for _, addr := range paddrs { - buf.WriteString("\t" + addr + "\n") + fmt.Fprintf(w, "\t"+addr+"\n") } } - return buf, nil - }, + return nil + }), }, Type: addrMap{}, } @@ -305,36 +290,37 @@ var swarmAddrsLocalCmd = &cmds.Command{ Options: []cmdkit.Option{ cmdkit.BoolOption("id", "Show peer ID in addresses."), }, - Run: func(req cmds.Request, res cmds.Response) { - iCtx := req.InvocContext() - n, err := iCtx.GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return + showid, _ := req.Options["id"].(bool) + self, err := api.Key().Self(req.Context) + if err != nil { + return err } - showid, _, _ := req.Option("id").Bool() - id := n.Identity.Pretty() + maddrs, err := api.Swarm().LocalAddrs(req.Context) + if err != nil { + return err + } var addrs []string - for _, addr := range n.PeerHost.Addrs() { + for _, addr := range maddrs { saddr := addr.String() if showid { - saddr = path.Join(saddr, "ipfs", id) + saddr = path.Join(saddr, "ipfs", self.ID().Pretty()) } addrs = append(addrs, saddr) } sort.Sort(sort.StringSlice(addrs)) - res.SetOutput(&stringList{addrs}) + return cmds.EmitOnce(res, &stringList{addrs}) }, Type: stringList{}, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, } @@ -345,24 +331,16 @@ var swarmAddrsListenCmd = &cmds.Command{ 'ipfs swarm addrs listen' lists all interface addresses the node is listening on. `, }, - Run: func(req cmds.Request, res cmds.Response) { - - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return + return err } var addrs []string - maddrs, err := n.PeerHost.Network().InterfaceListenAddresses() + maddrs, err := api.Swarm().ListenAddrs(req.Context) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } for _, addr := range maddrs { @@ -370,11 +348,11 @@ var swarmAddrsListenCmd = &cmds.Command{ } sort.Sort(sort.StringSlice(addrs)) - res.SetOutput(&stringList{addrs}) + return cmds.EmitOnce(res, &stringList{addrs}) }, Type: stringList{}, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, } @@ -392,53 +370,34 @@ ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3 Arguments: []cmdkit.Argument{ cmdkit.StringArg("address", true, true, "Address of peer to connect to.").EnableStdin(), }, - Run: func(req cmds.Request, res cmds.Response) { - ctx := req.Context() - - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - addrs := req.Arguments() - - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return - } - - // FIXME(steb): Nasty - swrm, ok := n.PeerHost.Network().(*swarm.Swarm) - if !ok { - res.SetError(fmt.Errorf("peerhost network was not swarm"), cmdkit.ErrNormal) - return - } + addrs := req.Arguments pis, err := peersWithAddresses(addrs) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } output := make([]string, len(pis)) for i, pi := range pis { - swrm.Backoff().Clear(pi.ID) - output[i] = "connect " + pi.ID.Pretty() - err := n.PeerHost.Connect(ctx, pi) + err := api.Swarm().Connect(req.Context, pi) if err != nil { - res.SetError(fmt.Errorf("%s failure: %s", output[i], err), cmdkit.ErrNormal) - return + return fmt.Errorf("%s failure: %s", output[i], err) } output[i] += " success" } - res.SetOutput(&stringList{output}) + return cmds.EmitOnce(res, &stringList{output}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, Type: stringList{}, } @@ -459,91 +418,35 @@ it will reconnect. Arguments: []cmdkit.Argument{ cmdkit.StringArg("address", true, true, "Address of peer to disconnect from.").EnableStdin(), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + api, err := cmdenv.GetApi(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - addrs := req.Arguments() - - if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrClient) - return - } - - iaddrs, err := parseAddresses(addrs) + iaddrs, err := parseAddresses(req.Arguments) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } output := make([]string, len(iaddrs)) for i, addr := range iaddrs { - taddr := addr.Transport() - id := addr.ID() - output[i] = "disconnect " + id.Pretty() + output[i] = "disconnect " + addr.ID().Pretty() - net := n.PeerHost.Network() - - if taddr == nil { - if net.Connectedness(id) != inet.Connected { - output[i] += " failure: not connected" - } else if err := net.ClosePeer(id); err != nil { - output[i] += " failure: " + err.Error() - } else { - output[i] += " success" - } + if err := api.Swarm().Disconnect(req.Context, addr.Multiaddr()); err != nil { + output[i] += " failure: " + err.Error() } else { - found := false - for _, conn := range net.ConnsToPeer(id) { - if !conn.RemoteMultiaddr().Equal(taddr) { - continue - } - - if err := conn.Close(); err != nil { - output[i] += " failure: " + err.Error() - } else { - output[i] += " success" - } - found = true - break - } - - if !found { - output[i] += " failure: conn not found" - } + output[i] += " success" } } - res.SetOutput(&stringList{output}) + return cmds.EmitOnce(res, &stringList{output}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, Type: stringList{}, } -func stringListMarshaler(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - - list, ok := v.(*stringList) - if !ok { - return nil, e.TypeErr(list, v) - } - - buf := new(bytes.Buffer) - for _, s := range list.Strings { - buf.WriteString(s) - buf.WriteString("\n") - } - - return buf, nil -} - // parseAddresses is a function that takes in a slice of string peer addresses // (multiaddr + peerid) and returns slices of multiaddrs and peerids. func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) { @@ -608,38 +511,34 @@ Filters default to those specified under the "Swarm.AddrFilters" config key. "add": swarmFiltersAddCmd, "rm": swarmFiltersRmCmd, }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := cmdenv.GetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrNormal) - return + return ErrNotOnline } // FIXME(steb) swrm, ok := n.PeerHost.Network().(*swarm.Swarm) if !ok { - res.SetError(errors.New("failed to cast network to swarm network"), cmdkit.ErrNormal) - return + return errors.New("failed to cast network to swarm network") } var output []string for _, f := range swrm.Filters.Filters() { s, err := mafilter.ConvertIPNet(f) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } output = append(output, s) } - res.SetOutput(&stringList{output}) + return cmds.EmitOnce(res, &stringList{output}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, Type: stringList{}, } @@ -656,63 +555,54 @@ add your filters to the ipfs config file. Arguments: []cmdkit.Argument{ cmdkit.StringArg("address", true, true, "Multiaddr to filter.").EnableStdin(), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := cmdenv.GetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrNormal) - return + return ErrNotOnline } // FIXME(steb) swrm, ok := n.PeerHost.Network().(*swarm.Swarm) if !ok { - res.SetError(errors.New("failed to cast network to swarm network"), cmdkit.ErrNormal) - return + return errors.New("failed to cast network to swarm network") } - if len(req.Arguments()) == 0 { - res.SetError(errors.New("no filters to add"), cmdkit.ErrClient) - return + if len(req.Arguments) == 0 { + return errors.New("no filters to add") } - r, err := fsrepo.Open(req.InvocContext().ConfigRoot) + r, err := fsrepo.Open(env.(*commands.Context).ConfigRoot) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } defer r.Close() cfg, err := r.Config() if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - for _, arg := range req.Arguments() { + for _, arg := range req.Arguments { mask, err := mafilter.NewMask(arg) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } swrm.Filters.AddDialFilter(mask) } - added, err := filtersAdd(r, cfg, req.Arguments()) + added, err := filtersAdd(r, cfg, req.Arguments) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - + return err } - res.SetOutput(&stringList{added}) + return cmds.EmitOnce(res, &stringList{added}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, Type: stringList{}, } @@ -729,37 +619,32 @@ remove your filters from the ipfs config file. Arguments: []cmdkit.Argument{ cmdkit.StringArg("address", true, true, "Multiaddr filter to remove.").EnableStdin(), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := req.InvocContext().GetNode() + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := cmdenv.GetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } if n.PeerHost == nil { - res.SetError(ErrNotOnline, cmdkit.ErrNormal) - return + return ErrNotOnline } swrm, ok := n.PeerHost.Network().(*swarm.Swarm) if !ok { - res.SetError(errors.New("failed to cast network to swarm network"), cmdkit.ErrNormal) - return + return errors.New("failed to cast network to swarm network") } - r, err := fsrepo.Open(req.InvocContext().ConfigRoot) + r, err := fsrepo.Open(env.(*commands.Context).ConfigRoot) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } defer r.Close() cfg, err := r.Config() if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - if req.Arguments()[0] == "all" || req.Arguments()[0] == "*" { + if req.Arguments[0] == "all" || req.Arguments[0] == "*" { fs := swrm.Filters.Filters() for _, f := range fs { swrm.Filters.Remove(f) @@ -767,35 +652,30 @@ remove your filters from the ipfs config file. removed, err := filtersRemoveAll(r, cfg) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - res.SetOutput(&stringList{removed}) - - return + return cmds.EmitOnce(res, &stringList{removed}) } - for _, arg := range req.Arguments() { + for _, arg := range req.Arguments { mask, err := mafilter.NewMask(arg) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } swrm.Filters.Remove(mask) } - removed, err := filtersRemove(r, cfg, req.Arguments()) + removed, err := filtersRemove(r, cfg, req.Arguments) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - res.SetOutput(&stringList{removed}) + return cmds.EmitOnce(res, &stringList{removed}) }, - Marshalers: cmds.MarshalerMap{ - cmds.Text: stringListMarshaler, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeEncoder(stringListEncoder), }, Type: stringList{}, } diff --git a/core/commands/tar.go b/core/commands/tar.go index a2fa3da20..ad65bff3e 100644 --- a/core/commands/tar.go +++ b/core/commands/tar.go @@ -7,10 +7,10 @@ import ( cmds "github.com/ipfs/go-ipfs/commands" core "github.com/ipfs/go-ipfs/core" e "github.com/ipfs/go-ipfs/core/commands/e" - "github.com/ipfs/go-ipfs/core/coreunix" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" tar "github.com/ipfs/go-ipfs/tar" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" ) @@ -60,12 +60,12 @@ represent it. c := node.Cid() fi.FileName() - res.SetOutput(&coreunix.AddedObject{ + res.SetOutput(&coreiface.AddEvent{ Name: fi.FileName(), Hash: c.String(), }) }, - Type: coreunix.AddedObject{}, + Type: coreiface.AddEvent{}, Marshalers: cmds.MarshalerMap{ cmds.Text: func(res cmds.Response) (io.Reader, error) { v, err := unwrapOutput(res.Output()) @@ -73,7 +73,7 @@ represent it. return nil, err } - o, ok := v.(*coreunix.AddedObject) + o, ok := v.(*coreiface.AddEvent) if !ok { return nil, e.TypeErr(o, v) } diff --git a/core/commands/unixfs/ls.go b/core/commands/unixfs/ls.go index 598823cfa..556bc2bd1 100644 --- a/core/commands/unixfs/ls.go +++ b/core/commands/unixfs/ls.go @@ -7,16 +7,13 @@ import ( "sort" "text/tabwriter" - cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - cmds "github.com/ipfs/go-ipfs/commands" - core "github.com/ipfs/go-ipfs/core" e "github.com/ipfs/go-ipfs/core/commands/e" - unixfs "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + iface "github.com/ipfs/go-ipfs/core/coreapi/interface" + + unixfs "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ) type LsLink struct { @@ -82,6 +79,12 @@ possible, please use 'ipfs ls' instead. return } + api, err := req.InvocContext().GetApi() + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return + } + paths := req.Arguments() output := LsOutput{ @@ -89,15 +92,16 @@ possible, please use 'ipfs ls' instead. Objects: map[string]*LsObject{}, } - for _, fpath := range paths { + for _, p := range paths { ctx := req.Context() - resolver := &resolver.Resolver{ - DAG: node.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, + fpath, err := iface.ParsePath(p) + if err != nil { + res.SetError(err, cmdkit.ErrNormal) + return } - merkleNode, err := core.Resolve(ctx, node.Namesys, resolver, path.Path(fpath)) + merkleNode, err := api.ResolveNode(ctx, fpath) if err != nil { res.SetError(err, cmdkit.ErrNormal) return @@ -106,7 +110,7 @@ possible, please use 'ipfs ls' instead. c := merkleNode.Cid() hash := c.String() - output.Arguments[fpath] = hash + output.Arguments[p] = hash if _, ok := output.Objects[hash]; ok { // duplicate argument for an already-listed node diff --git a/core/commands/urlstore.go b/core/commands/urlstore.go index 8769130c3..d29f4e6fb 100644 --- a/core/commands/urlstore.go +++ b/core/commands/urlstore.go @@ -10,12 +10,12 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" + balanced "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/balanced" + ihelper "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/helpers" + trickle "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/trickle" cmdkit "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit" - balanced "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/balanced" - ihelper "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/helpers" - trickle "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/trickle" - chunk "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" + chunk "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" ) var urlStoreCmd = &cmds.Command{ diff --git a/core/commands/version.go b/core/commands/version.go index 434eec715..9886cfe1a 100644 --- a/core/commands/version.go +++ b/core/commands/version.go @@ -22,6 +22,13 @@ type VersionOutput struct { Golang string } +const ( + versionNumberOptionName = "number" + versionCommitOptionName = "commit" + versionRepoOptionName = "repo" + versionAllOptionName = "all" +) + var VersionCmd = &cmds.Command{ Helptext: cmdkit.HelpText{ Tagline: "Show ipfs version information.", @@ -29,10 +36,10 @@ var VersionCmd = &cmds.Command{ }, Options: []cmdkit.Option{ - cmdkit.BoolOption("number", "n", "Only show the version number."), - cmdkit.BoolOption("commit", "Show the commit hash."), - cmdkit.BoolOption("repo", "Show repo version."), - cmdkit.BoolOption("all", "Show all version information"), + cmdkit.BoolOption(versionNumberOptionName, "n", "Only show the version number."), + cmdkit.BoolOption(versionCommitOptionName, "Show the commit hash."), + cmdkit.BoolOption(versionRepoOptionName, "Show repo version."), + cmdkit.BoolOption(versionAllOptionName, "Show all version information"), }, Run: func(req cmds.Request, res cmds.Response) { res.SetOutput(&VersionOutput{ @@ -55,7 +62,7 @@ var VersionCmd = &cmds.Command{ return nil, e.TypeErr(version, v) } - repo, _, err := res.Request().Option("repo").Bool() + repo, _, err := res.Request().Option(versionRepoOptionName).Bool() if err != nil { return nil, err } @@ -64,7 +71,7 @@ var VersionCmd = &cmds.Command{ return strings.NewReader(version.Repo + "\n"), nil } - commit, _, err := res.Request().Option("commit").Bool() + commit, _, err := res.Request().Option(versionCommitOptionName).Bool() commitTxt := "" if err != nil { return nil, err @@ -73,7 +80,7 @@ var VersionCmd = &cmds.Command{ commitTxt = "-" + version.Commit } - number, _, err := res.Request().Option("number").Bool() + number, _, err := res.Request().Option(versionNumberOptionName).Bool() if err != nil { return nil, err } @@ -81,7 +88,7 @@ var VersionCmd = &cmds.Command{ return strings.NewReader(fmt.Sprintln(version.Version + commitTxt)), nil } - all, _, err := res.Request().Option("all").Bool() + all, _, err := res.Request().Option(versionAllOptionName).Bool() if err != nil { return nil, err } diff --git a/core/core.go b/core/core.go index 7cbaf705c..2aea5e466 100644 --- a/core/core.go +++ b/core/core.go @@ -30,53 +30,53 @@ import ( pin "github.com/ipfs/go-ipfs/pin" repo "github.com/ipfs/go-ipfs/repo" + pnet "gx/ipfs/QmNmyLmysLFuSRjNTW8XrbovrNYFbZoMknTcpYR2AvvDc3/go-libp2p-pnet" metrics "gx/ipfs/QmNn6gcjBXpg8kccr9zEV7UVBpqAw8FZEiQ6DksvzyTQ5K/go-libp2p-metrics" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - quic "gx/ipfs/QmPWMfcxNC7txnUvT21xdivgRJfJ9e7YuC5nCn6JEALFQv/go-libp2p-quic-transport" - psrouter "gx/ipfs/QmPbLCBNGvyQhs3xK64cbobq7sN1Hdn6Ud9pkhsZME1sqT/go-libp2p-pubsub-router" - floodsub "gx/ipfs/QmPbYVFhKxamZAN9MyrQMDeoGYa6zkQkhAPguwFfzxPM1J/go-libp2p-floodsub" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" ic "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + bitswap "gx/ipfs/QmQHbKeMWRNT8koMhh2DrTXZWepYVoGPNXni6JG1L3BhGq/go-bitswap" + bsnet "gx/ipfs/QmQHbKeMWRNT8koMhh2DrTXZWepYVoGPNXni6JG1L3BhGq/go-bitswap/network" + p2phost "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" + "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path/resolver" + nilrouting "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/none" + offroute "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" + mplex "gx/ipfs/QmQvMxiavoMJzuLPuqrzVX4nXZpMks29hqpv13d81aJNEF/go-smux-multiplex" exchange "gx/ipfs/QmR1nncPsZR14A4hWr39mq8Lm7BGgS68bHVT9nop8NpWEM/go-ipfs-exchange-interface" - circuit "gx/ipfs/QmS5X31wA86RSjQqCUHG2CLPoFNnBZ3UMy1ikfBHQ3G6LG/go-libp2p-circuit" goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" mamask "gx/ipfs/QmSMZwvs3n4GBikZ7hKzT17c3bk65FmyZo2JqtJ16swqCv/multiaddr-filter" mafilter "gx/ipfs/QmSW4uNHbvQia8iZDXzbwjiyHQtnyo9aFqfQAMasj3TJ6Y/go-maddr-filter" record "gx/ipfs/QmSb4B8ZAAj5ALe9LjfzPyF8Ma6ezC1NTnDF2JQPUJxEXb/go-libp2p-record" - nilrouting "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/none" - offroute "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" - connmgr "gx/ipfs/QmSw6zWpuKvcHne7AjNS3LdmcPm1iUq5qd1z1KgVib7QnM/go-libp2p-connmgr" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - bitswap "gx/ipfs/QmUdtRsAr9RYxqNwUzeHDhv5bnVppiHLixP1SU4YysVj2S/go-bitswap" - bsnet "gx/ipfs/QmUdtRsAr9RYxqNwUzeHDhv5bnVppiHLixP1SU4YysVj2S/go-bitswap/network" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - ifconnmgr "gx/ipfs/QmV9T3rTezwJhMJQBzVrGj2tncJwv23dTKdxzXrUxAvWFi/go-libp2p-interface-connmgr" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" - libp2p "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p" - discovery "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/discovery" - p2pbhost "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/host/basic" - rhost "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/host/routed" - identify "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/protocol/identify" - ping "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/protocol/ping" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + dht "gx/ipfs/QmTdMq4uYZXmGW3u6KgnpCRWjo1Y7dWjRuAaGPw7Qxqr1s/go-libp2p-kad-dht" + dhtopts "gx/ipfs/QmTdMq4uYZXmGW3u6KgnpCRWjo1Y7dWjRuAaGPw7Qxqr1s/go-libp2p-kad-dht/opts" + libp2p "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p" + discovery "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/discovery" + p2pbhost "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/host/basic" + rhost "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/host/routed" + identify "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/protocol/identify" + ping "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/protocol/ping" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + ifconnmgr "gx/ipfs/QmXPqoktJEKkWPT6rSdhCM2G3E1yR7uUBdjnJrhJYeBgHU/go-libp2p-interface-connmgr" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" smux "gx/ipfs/QmY9JXR3FupnYAYJWK9aMr9bCpqWKcToQ1tz8DVGTrHpHw/go-stream-muxer" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" - mplex "gx/ipfs/QmYsbnP57nNUKWijs8o2q3ZFrSUcAGTdKoQPuSJC3Uxt1Y/go-smux-multiplex" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - dht "gx/ipfs/QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME/go-libp2p-kad-dht" - dhtopts "gx/ipfs/QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME/go-libp2p-kad-dht/opts" - pnet "gx/ipfs/QmZaQ3K9PRd5sYYoG1xbTGPtd3N7TYiKBRmcBUTsx8HVET/go-libp2p-pnet" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" + connmgr "gx/ipfs/QmZygFpFQfDwTNeU8AYTfEgAXfb7yfuQh9L4wYG7GgtcMH/go-libp2p-connmgr" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - rhelpers "gx/ipfs/QmcRdSdYkL17qhuQAibF5D14XdQ1iunvaVnXGjDiQTdRm9/go-libp2p-routing-helpers" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" - yamux "gx/ipfs/QmcsgrV3nCAKjiHKZhKVXWc4oY3WBECJCqahXEMpHeMrev/go-smux-yamux" + floodsub "gx/ipfs/Qmbi2MdNz6bdqWJg9Fud3WCqTdzP4DXKBwYD16EJVkjzKX/go-libp2p-floodsub" + quic "gx/ipfs/QmbxTJyyqtyYYM7wLHWv529e2dwzt9a9o8FfVQALvPpadC/go-libp2p-quic-transport" + psrouter "gx/ipfs/QmbyoYqzgpaKt97AEoAx4zJCuHdQ71GNkpVZwhJ1wUtzba/go-libp2p-pubsub-router" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" - p2phost "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + yamux "gx/ipfs/QmejxafYByb7s4rEMoKjmThZm6HfQ1seASNejVNKde6LBZ/go-smux-yamux" + circuit "gx/ipfs/Qmf5M8FECT1H1NGZ9kM6Ri4G4LfQGJcyMpfMPEA1herPuH/go-libp2p-circuit" + rhelpers "gx/ipfs/QmfGNszPuruiURVbgyvoj7eoVe9bkj2uHugMZVteX9zxD1/go-libp2p-routing-helpers" ) const IpnsValidatorTag = "ipns" diff --git a/core/core_test.go b/core/core_test.go index 2d0a592c6..fc920ce53 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -7,9 +7,9 @@ import ( "github.com/ipfs/go-ipfs/repo" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" ) func TestInitialization(t *testing.T) { @@ -21,7 +21,7 @@ func TestInitialization(t *testing.T) { Identity: id, Addresses: config.Addresses{ Swarm: []string{"/ip4/0.0.0.0/tcp/4001"}, - API: "/ip4/127.0.0.1/tcp/8000", + API: []string{"/ip4/127.0.0.1/tcp/8000"}, }, }, @@ -29,7 +29,7 @@ func TestInitialization(t *testing.T) { Identity: id, Addresses: config.Addresses{ Swarm: []string{"/ip4/0.0.0.0/tcp/4001"}, - API: "/ip4/127.0.0.1/tcp/8000", + API: []string{"/ip4/127.0.0.1/tcp/8000"}, }, }, } diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index bb7afd61a..ba6082626 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -16,8 +16,12 @@ package coreapi import ( core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + + logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" ) +var log = logging.Logger("core/coreapi") + type CoreAPI struct { node *core.IpfsNode } @@ -67,3 +71,13 @@ func (api *CoreAPI) Pin() coreiface.PinAPI { func (api *CoreAPI) Dht() coreiface.DhtAPI { return (*DhtAPI)(api) } + +// Swarm returns the SwarmAPI interface implementation backed by the go-ipfs node +func (api *CoreAPI) Swarm() coreiface.SwarmAPI { + return (*SwarmAPI)(api) +} + +// PubSub returns the PubSubAPI interface implementation backed by the go-ipfs node +func (api *CoreAPI) PubSub() coreiface.PubSubAPI { + return (*PubSubAPI)(api) +} diff --git a/core/coreapi/dht.go b/core/coreapi/dht.go index 388b33b85..39a296444 100644 --- a/core/coreapi/dht.go +++ b/core/coreapi/dht.go @@ -10,13 +10,13 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + blockservice "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - blockservice "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) type DhtAPI CoreAPI diff --git a/core/coreapi/interface/coreapi.go b/core/coreapi/interface/coreapi.go index 0053d472e..bc889237b 100644 --- a/core/coreapi/interface/coreapi.go +++ b/core/coreapi/interface/coreapi.go @@ -34,6 +34,12 @@ type CoreAPI interface { // Dht returns an implementation of Dht API Dht() DhtAPI + // Swarm returns an implementation of Swarm API + Swarm() SwarmAPI + + // PubSub returns an implementation of PubSub API + PubSub() PubSubAPI + // ResolvePath resolves the path using Unixfs resolver ResolvePath(context.Context, Path) (ResolvedPath, error) diff --git a/core/coreapi/interface/dht.go b/core/coreapi/interface/dht.go index 2309ceb90..3096c8fb7 100644 --- a/core/coreapi/interface/dht.go +++ b/core/coreapi/interface/dht.go @@ -5,8 +5,8 @@ import ( "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) // DhtAPI specifies the interface to the DHT diff --git a/core/coreapi/interface/errors.go b/core/coreapi/interface/errors.go index 81f978971..072275409 100644 --- a/core/coreapi/interface/errors.go +++ b/core/coreapi/interface/errors.go @@ -4,5 +4,5 @@ import "errors" var ( ErrIsDir = errors.New("object is a directory") - ErrOffline = errors.New("can't resolve, ipfs node is offline") + ErrOffline = errors.New("this action must be run in online mode, try running 'ipfs daemon' first") ) diff --git a/core/coreapi/interface/key.go b/core/coreapi/interface/key.go index 4305ae20d..cc6dc8900 100644 --- a/core/coreapi/interface/key.go +++ b/core/coreapi/interface/key.go @@ -33,6 +33,9 @@ type KeyAPI interface { // List lists keys stored in keystore List(ctx context.Context) ([]Key, error) + // Self returns the 'main' node key + Self(ctx context.Context) (Key, error) + // Remove removes keys from keystore. Returns ipns path of the removed key Remove(ctx context.Context, name string) (Key, error) } diff --git a/core/coreapi/interface/name.go b/core/coreapi/interface/name.go index a6aad0c3e..14127ac27 100644 --- a/core/coreapi/interface/name.go +++ b/core/coreapi/interface/name.go @@ -3,9 +3,13 @@ package iface import ( "context" + "errors" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" ) +var ErrResolveFailed = errors.New("could not resolve name") + // IpnsEntry specifies the interface to IpnsEntries type IpnsEntry interface { // Name returns IpnsEntry name @@ -14,6 +18,11 @@ type IpnsEntry interface { Value() Path } +type IpnsResult struct { + Path + Err error +} + // NameAPI specifies the interface to IPNS. // // IPNS is a PKI namespace, where names are the hashes of public keys, and the @@ -28,4 +37,11 @@ type NameAPI interface { // Resolve attempts to resolve the newest version of the specified name Resolve(ctx context.Context, name string, opts ...options.NameResolveOption) (Path, error) + + // Search is a version of Resolve which outputs paths as they are discovered, + // reducing the time to first entry + // + // Note that by default only the last path returned before the channel closes + // can be considered 'safe'. + Search(ctx context.Context, name string, opts ...options.NameResolveOption) (<-chan IpnsResult, error) } diff --git a/core/coreapi/interface/options/name.go b/core/coreapi/interface/options/name.go index ba3691b03..c614db3ab 100644 --- a/core/coreapi/interface/options/name.go +++ b/core/coreapi/interface/options/name.go @@ -13,6 +13,10 @@ const ( type NamePublishSettings struct { ValidTime time.Duration Key string + + TTL *time.Duration + + AllowOffline bool } type NameResolveSettings struct { @@ -29,6 +33,8 @@ func NamePublishOptions(opts ...NamePublishOption) (*NamePublishSettings, error) options := &NamePublishSettings{ ValidTime: DefaultNameValidTime, Key: "self", + + AllowOffline: false, } for _, opt := range opts { @@ -82,6 +88,24 @@ func (nameOpts) Key(key string) NamePublishOption { } } +// AllowOffline is an option for Name.Publish which specifies whether to allow +// publishing when the node is offline. Default value is false +func (nameOpts) AllowOffline(allow bool) NamePublishOption { + return func(settings *NamePublishSettings) error { + settings.AllowOffline = allow + return nil + } +} + +// TTL is an option for Name.Publish which specifies the time duration the +// published record should be cached for (caution: experimental). +func (nameOpts) TTL(ttl time.Duration) NamePublishOption { + return func(settings *NamePublishSettings) error { + settings.TTL = &ttl + return nil + } +} + // Local is an option for Name.Resolve which specifies if the lookup should be // offline. Default value is false func (nameOpts) Local(local bool) NameResolveOption { diff --git a/core/coreapi/interface/options/pubsub.go b/core/coreapi/interface/options/pubsub.go new file mode 100644 index 000000000..c387d613d --- /dev/null +++ b/core/coreapi/interface/options/pubsub.go @@ -0,0 +1,58 @@ +package options + +type PubSubPeersSettings struct { + Topic string +} + +type PubSubSubscribeSettings struct { + Discover bool +} + +type PubSubPeersOption func(*PubSubPeersSettings) error +type PubSubSubscribeOption func(*PubSubSubscribeSettings) error + +func PubSubPeersOptions(opts ...PubSubPeersOption) (*PubSubPeersSettings, error) { + options := &PubSubPeersSettings{ + Topic: "", + } + + for _, opt := range opts { + err := opt(options) + if err != nil { + return nil, err + } + } + return options, nil +} + +func PubSubSubscribeOptions(opts ...PubSubSubscribeOption) (*PubSubSubscribeSettings, error) { + options := &PubSubSubscribeSettings{ + Discover: false, + } + + for _, opt := range opts { + err := opt(options) + if err != nil { + return nil, err + } + } + return options, nil +} + +type pubsubOpts struct{} + +var PubSub pubsubOpts + +func (pubsubOpts) Topic(topic string) PubSubPeersOption { + return func(settings *PubSubPeersSettings) error { + settings.Topic = topic + return nil + } +} + +func (pubsubOpts) Discover(discover bool) PubSubSubscribeOption { + return func(settings *PubSubSubscribeSettings) error { + settings.Discover = discover + return nil + } +} diff --git a/core/coreapi/interface/options/unixfs.go b/core/coreapi/interface/options/unixfs.go new file mode 100644 index 000000000..b4661b793 --- /dev/null +++ b/core/coreapi/interface/options/unixfs.go @@ -0,0 +1,304 @@ +package options + +import ( + "errors" + "fmt" + + cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" +) + +type Layout int + +const ( + BalancedLayout Layout = iota + TrickleLayout +) + +type UnixfsAddSettings struct { + CidVersion int + MhType uint64 + + Inline bool + InlineLimit int + RawLeaves bool + RawLeavesSet bool + + Chunker string + Layout Layout + + Pin bool + OnlyHash bool + Local bool + FsCache bool + NoCopy bool + + Wrap bool + Hidden bool + StdinName string + + Events chan<- interface{} + Silent bool + Progress bool +} + +type UnixfsAddOption func(*UnixfsAddSettings) error + +func UnixfsAddOptions(opts ...UnixfsAddOption) (*UnixfsAddSettings, cid.Prefix, error) { + options := &UnixfsAddSettings{ + CidVersion: -1, + MhType: mh.SHA2_256, + + Inline: false, + InlineLimit: 32, + RawLeaves: false, + RawLeavesSet: false, + + Chunker: "size-262144", + Layout: BalancedLayout, + + Pin: false, + OnlyHash: false, + Local: false, + FsCache: false, + NoCopy: false, + + Wrap: false, + Hidden: false, + StdinName: "", + + Events: nil, + Silent: false, + Progress: false, + } + + for _, opt := range opts { + err := opt(options) + if err != nil { + return nil, cid.Prefix{}, err + } + } + + // nocopy -> rawblocks + if options.NoCopy && !options.RawLeaves { + // fixed? + if options.RawLeavesSet { + return nil, cid.Prefix{}, fmt.Errorf("nocopy option requires '--raw-leaves' to be enabled as well") + } + + // No, satisfy mandatory constraint. + options.RawLeaves = true + } + + // (hash != "sha2-256") -> CIDv1 + if options.MhType != mh.SHA2_256 { + switch options.CidVersion { + case 0: + return nil, cid.Prefix{}, errors.New("CIDv0 only supports sha2-256") + case 1, -1: + options.CidVersion = 1 + default: + return nil, cid.Prefix{}, fmt.Errorf("unknown CID version: %d", options.CidVersion) + } + } else { + if options.CidVersion < 0 { + // Default to CIDv0 + options.CidVersion = 0 + } + } + + // cidV1 -> raw blocks (by default) + if options.CidVersion > 0 && !options.RawLeavesSet { + options.RawLeaves = true + } + + prefix, err := dag.PrefixForCidVersion(options.CidVersion) + if err != nil { + return nil, cid.Prefix{}, err + } + + prefix.MhType = options.MhType + prefix.MhLength = -1 + + return options, prefix, nil +} + +type unixfsOpts struct{} + +var Unixfs unixfsOpts + +// CidVersion specifies which CID version to use. Defaults to 0 unless an option +// that depends on CIDv1 is passed. +func (unixfsOpts) CidVersion(version int) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.CidVersion = version + return nil + } +} + +// Hash function to use. Implies CIDv1 if not set to sha2-256 (default). +// +// Table of functions is declared in https://github.com/multiformats/go-multihash/blob/master/multihash.go +func (unixfsOpts) Hash(mhtype uint64) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.MhType = mhtype + return nil + } +} + +// RawLeaves specifies whether to use raw blocks for leaves (data nodes with no +// links) instead of wrapping them with unixfs structures. +func (unixfsOpts) RawLeaves(enable bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.RawLeaves = enable + settings.RawLeavesSet = true + return nil + } +} + +// Inline tells the adder to inline small blocks into CIDs +func (unixfsOpts) Inline(enable bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Inline = enable + return nil + } +} + +// InlineLimit sets the amount of bytes below which blocks will be encoded +// directly into CID instead of being stored and addressed by it's hash. +// Specifying this option won't enable block inlining. For that use `Inline` +// option. Default: 32 bytes +// +// Note that while there is no hard limit on the number of bytes, it should be +// kept at a reasonably low value, such as 64; implementations may choose to +// reject anything larger. +func (unixfsOpts) InlineLimit(limit int) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.InlineLimit = limit + return nil + } +} + +// Chunker specifies settings for the chunking algorithm to use. +// +// Default: size-262144, formats: +// size-[bytes] - Simple chunker splitting data into blocks of n bytes +// rabin-[min]-[avg]-[max] - Rabin chunker +func (unixfsOpts) Chunker(chunker string) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Chunker = chunker + return nil + } +} + +// Layout tells the adder how to balance data between leaves. +// options.BalancedLayout is the default, it's optimized for static seekable +// files. +// options.TrickleLayout is optimized for streaming data, +func (unixfsOpts) Layout(layout Layout) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Layout = layout + return nil + } +} + +// Pin tells the adder to pin the file root recursively after adding +func (unixfsOpts) Pin(pin bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Pin = pin + return nil + } +} + +// HashOnly will make the adder calculate data hash without storing it in the +// blockstore or announcing it to the network +func (unixfsOpts) HashOnly(hashOnly bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.OnlyHash = hashOnly + return nil + } +} + +// Local will add the data to blockstore without announcing it to the network +// +// Note that this doesn't prevent other nodes from getting this data +func (unixfsOpts) Local(local bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Local = local + return nil + } +} + +// Wrap tells the adder to wrap the added file structure with an additional +// directory. +func (unixfsOpts) Wrap(wrap bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Wrap = wrap + return nil + } +} + +// Hidden enables adding of hidden files (files prefixed with '.') +func (unixfsOpts) Hidden(hidden bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Hidden = hidden + return nil + } +} + +// StdinName is the name set for files which don specify FilePath as +// os.Stdin.Name() +func (unixfsOpts) StdinName(name string) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.StdinName = name + return nil + } +} + +// Events specifies channel which will be used to report events about ongoing +// Add operation. +// +// Note that if this channel blocks it may slowdown the adder +func (unixfsOpts) Events(sink chan<- interface{}) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Events = sink + return nil + } +} + +// Silent reduces event output +func (unixfsOpts) Silent(silent bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Silent = silent + return nil + } +} + +// Progress tells the adder whether to enable progress events +func (unixfsOpts) Progress(enable bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.Progress = enable + return nil + } +} + +// FsCache tells the adder to check the filestore for pre-existing blocks +// +// Experimental +func (unixfsOpts) FsCache(enable bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.FsCache = enable + return nil + } +} + +// NoCopy tells the adder to add the files using filestore. Implies RawLeaves. +// +// Experimental +func (unixfsOpts) Nocopy(enable bool) UnixfsAddOption { + return func(settings *UnixfsAddSettings) error { + settings.NoCopy = enable + return nil + } +} diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index 0beab0663..9bb46b4b4 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -1,7 +1,7 @@ package iface import ( - ipfspath "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ipfspath "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ) diff --git a/core/coreapi/interface/pubsub.go b/core/coreapi/interface/pubsub.go new file mode 100644 index 000000000..d7a21e02f --- /dev/null +++ b/core/coreapi/interface/pubsub.go @@ -0,0 +1,48 @@ +package iface + +import ( + "context" + "io" + + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + + peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" +) + +// PubSubSubscription is an active PubSub subscription +type PubSubSubscription interface { + io.Closer + + // Next return the next incoming message + Next(context.Context) (PubSubMessage, error) +} + +// PubSubMessage is a single PubSub message +type PubSubMessage interface { + // From returns id of a peer from which the message has arrived + From() peer.ID + + // Data returns the message body + Data() []byte + + // Seq returns message identifier + Seq() []byte + + // Topics returns list of topics this message was set to + Topics() []string +} + +// PubSubAPI specifies the interface to PubSub +type PubSubAPI interface { + // Ls lists subscribed topics by name + Ls(context.Context) ([]string, error) + + // Peers list peers we are currently pubsubbing with + Peers(context.Context, ...options.PubSubPeersOption) ([]peer.ID, error) + + // Publish a message to a given pubsub topic + Publish(context.Context, string, []byte) error + + // Subscribe to messages on a given topic + Subscribe(context.Context, string, ...options.PubSubSubscribeOption) (PubSubSubscription, error) +} diff --git a/core/coreapi/interface/swarm.go b/core/coreapi/interface/swarm.go new file mode 100644 index 000000000..d8bca395c --- /dev/null +++ b/core/coreapi/interface/swarm.go @@ -0,0 +1,57 @@ +package iface + +import ( + "context" + "errors" + "time" + + net "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" + "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" + "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" +) + +var ( + ErrNotConnected = errors.New("not connected") + ErrConnNotFound = errors.New("conn not found") +) + +// ConnectionInfo contains information about a peer +type ConnectionInfo interface { + // ID returns PeerID + ID() peer.ID + + // Address returns the multiaddress via which we are connected with the peer + Address() ma.Multiaddr + + // Direction returns which way the connection was established + Direction() net.Direction + + // Latency returns last known round trip time to the peer + Latency() (time.Duration, error) + + // Streams returns list of streams established with the peer + Streams() ([]protocol.ID, error) +} + +// SwarmAPI specifies the interface to libp2p swarm +type SwarmAPI interface { + // Connect to a given peer + Connect(context.Context, pstore.PeerInfo) error + + // Disconnect from a given address + Disconnect(context.Context, ma.Multiaddr) error + + // Peers returns the list of peers we are connected to + Peers(context.Context) ([]ConnectionInfo, error) + + // KnownAddrs returns the list of all addresses this node is aware of + KnownAddrs(context.Context) (map[peer.ID][]ma.Multiaddr, error) + + // LocalAddrs returns the list of announced listening addresses + LocalAddrs(context.Context) ([]ma.Multiaddr, error) + + // ListenAddrs returns the list of all listening addresses + ListenAddrs(context.Context) ([]ma.Multiaddr, error) +} diff --git a/core/coreapi/interface/unixfs.go b/core/coreapi/interface/unixfs.go index 4a3aff6fc..c622e210e 100644 --- a/core/coreapi/interface/unixfs.go +++ b/core/coreapi/interface/unixfs.go @@ -2,17 +2,37 @@ package iface import ( "context" - "io" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) +// TODO: ideas on making this more coreapi-ish without breaking the http API? +type AddEvent struct { + Name string + Hash string `json:",omitempty"` + Bytes int64 `json:",omitempty"` + Size string `json:",omitempty"` +} + // UnixfsAPI is the basic interface to immutable files in IPFS +// NOTE: This API is heavily WIP, things are guaranteed to break frequently type UnixfsAPI interface { // Add imports the data from the reader into merkledag file - Add(context.Context, io.Reader) (ResolvedPath, error) + // + // TODO: a long useful comment on how to use this for many different scenarios + Add(context.Context, files.File, ...options.UnixfsAddOption) (ResolvedPath, error) + + // Get returns a read-only handle to a file tree referenced by a path + // + // Note that some implementations of this API may apply the specified context + // to operations performed on the returned file + Get(context.Context, Path) (files.File, error) // Cat returns a reader for the file + // TODO: Remove in favour of Get (if we use Get on a file we still have reader directly, so..) Cat(context.Context, Path) (Reader, error) // Ls returns the list of links in a directory diff --git a/core/coreapi/interface/util.go b/core/coreapi/interface/util.go index 8fd3e058f..6d58bf40d 100644 --- a/core/coreapi/interface/util.go +++ b/core/coreapi/interface/util.go @@ -1,10 +1,20 @@ package iface import ( + "context" "io" ) type Reader interface { - io.ReadSeeker - io.Closer + ReadSeekCloser + Size() uint64 + CtxReadFull(context.Context, []byte) (int, error) +} + +// A ReadSeekCloser implements interfaces to read, copy, seek and close. +type ReadSeekCloser interface { + io.Reader + io.Seeker + io.Closer + io.WriterTo } diff --git a/core/coreapi/key.go b/core/coreapi/key.go index 9bc4e1aef..9e0460b7f 100644 --- a/core/coreapi/key.go +++ b/core/coreapi/key.go @@ -3,6 +3,7 @@ package coreapi import ( "context" "crypto/rand" + "errors" "fmt" "sort" @@ -10,8 +11,8 @@ import ( caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" crypto "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" + ipfspath "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - ipfspath "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) type KeyAPI CoreAPI @@ -216,3 +217,11 @@ func (api *KeyAPI) Remove(ctx context.Context, name string) (coreiface.Key, erro return &key{"", pid}, nil } + +func (api *KeyAPI) Self(ctx context.Context) (coreiface.Key, error) { + if api.node.Identity == "" { + return nil, errors.New("identity not loaded") + } + + return &key{"self", api.node.Identity}, nil +} diff --git a/core/coreapi/name.go b/core/coreapi/name.go index cb7fc9b7d..fd6a4daa7 100644 --- a/core/coreapi/name.go +++ b/core/coreapi/name.go @@ -7,15 +7,16 @@ import ( "strings" "time" + ipath "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" "github.com/ipfs/go-ipfs/keystore" "github.com/ipfs/go-ipfs/namesys" - ipath "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" + "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ) @@ -45,6 +46,9 @@ func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopt n := api.node if !n.OnlineMode() { + if !options.AllowOffline { + return nil, coreiface.ErrOffline + } err := n.SetupOfflineRouting() if err != nil { return nil, err @@ -65,6 +69,10 @@ func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopt return nil, err } + if options.TTL != nil { + ctx = context.WithValue(ctx, "ipns-publish-ttl", *options.TTL) + } + eol := time.Now().Add(options.ValidTime) err = n.Namesys.PublishWithEOL(ctx, k, pth, eol) if err != nil { @@ -82,9 +90,7 @@ func (api *NameAPI) Publish(ctx context.Context, p coreiface.Path, opts ...caopt }, nil } -// Resolve attempts to resolve the newest version of the specified name and -// returns its path. -func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.NameResolveOption) (coreiface.Path, error) { +func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.NameResolveOption) (<-chan coreiface.IpnsResult, error) { options, err := caopts.NameResolveOptions(opts...) if err != nil { return nil, err @@ -118,12 +124,42 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam name = "/ipns/" + name } - output, err := resolver.Resolve(ctx, name, options.ResolveOpts...) + out := make(chan coreiface.IpnsResult) + go func() { + defer close(out) + for res := range resolver.ResolveAsync(ctx, name, options.ResolveOpts...) { + p, _ := coreiface.ParsePath(res.Path.String()) + + select { + case out <- coreiface.IpnsResult{Path: p, Err: res.Err}: + case <-ctx.Done(): + return + } + } + }() + + return out, nil +} + +// Resolve attempts to resolve the newest version of the specified name and +// returns its path. +func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.NameResolveOption) (coreiface.Path, error) { + results, err := api.Search(ctx, name, opts...) if err != nil { return nil, err } - return coreiface.ParsePath(output.String()) + err = coreiface.ErrResolveFailed + var p coreiface.Path + + for res := range results { + p, err = res.Path, res.Err + if err != nil { + break + } + } + + return p, err } func keylookup(n *core.IpfsNode, k string) (crypto.PrivKey, error) { diff --git a/core/coreapi/name_test.go b/core/coreapi/name_test.go index d22666484..dd4c2cb3d 100644 --- a/core/coreapi/name_test.go +++ b/core/coreapi/name_test.go @@ -3,11 +3,13 @@ package coreapi_test import ( "context" "io" + "io/ioutil" "math/rand" "testing" "time" - ipath "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ipath "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options" @@ -16,7 +18,7 @@ import ( var rnd = rand.New(rand.NewSource(0x62796532303137)) func addTestObject(ctx context.Context, api coreiface.CoreAPI) (coreiface.Path, error) { - return api.Unixfs().Add(ctx, &io.LimitedReader{R: rnd, N: 4092}) + return api.Unixfs().Add(ctx, files.NewReaderFile("", "", ioutil.NopCloser(&io.LimitedReader{R: rnd, N: 4092}), nil)) } func TestBasicPublishResolve(t *testing.T) { diff --git a/core/coreapi/object.go b/core/coreapi/object.go index 7b9ba7719..b98427cb9 100644 --- a/core/coreapi/object.go +++ b/core/coreapi/object.go @@ -17,8 +17,8 @@ import ( "github.com/ipfs/go-ipfs/pin" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) diff --git a/core/coreapi/path.go b/core/coreapi/path.go index 989e4d75b..7d72b6d32 100644 --- a/core/coreapi/path.go +++ b/core/coreapi/path.go @@ -7,9 +7,9 @@ import ( "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - ipfspath "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + ipfspath "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path/resolver" "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index 3f1139b30..d3513e41e 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -7,11 +7,11 @@ import ( coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" corerepo "github.com/ipfs/go-ipfs/core/corerepo" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" ) type PinAPI CoreAPI @@ -22,19 +22,19 @@ func (api *PinAPI) Add(ctx context.Context, p coreiface.Path, opts ...caopts.Pin return err } - defer api.node.Blockstore.PinLock().Unlock() - rp, err := api.core().ResolvePath(ctx, p) if err != nil { return err } - _, err = corerepo.Pin(api.node, ctx, []string{rp.Cid().String()}, settings.Recursive) + defer api.node.Blockstore.PinLock().Unlock() + + _, err = corerepo.Pin(api.node, api.core(), ctx, []string{rp.Cid().String()}, settings.Recursive) if err != nil { return err } - return nil + return api.node.Pinning.Flush() } func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) ([]coreiface.Pin, error) { @@ -53,12 +53,12 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) ([]coreif } func (api *PinAPI) Rm(ctx context.Context, p coreiface.Path) error { - _, err := corerepo.Unpin(api.node, ctx, []string{p.String()}, true) + _, err := corerepo.Unpin(api.node, api.core(), ctx, []string{p.String()}, true) if err != nil { return err } - return nil + return api.node.Pinning.Flush() } func (api *PinAPI) Update(ctx context.Context, from coreiface.Path, to coreiface.Path, opts ...caopts.PinUpdateOption) error { @@ -77,7 +77,14 @@ func (api *PinAPI) Update(ctx context.Context, from coreiface.Path, to coreiface return err } - return api.node.Pinning.Update(ctx, fp.Cid(), tp.Cid(), settings.Unpin) + defer api.node.Blockstore.PinLock().Unlock() + + err = api.node.Pinning.Update(ctx, fp.Cid(), tp.Cid(), settings.Unpin) + if err != nil { + return err + } + + return api.node.Pinning.Flush() } type pinStatus struct { diff --git a/core/coreapi/pin_test.go b/core/coreapi/pin_test.go index 9bbf16c9c..a9a7547c3 100644 --- a/core/coreapi/pin_test.go +++ b/core/coreapi/pin_test.go @@ -15,7 +15,7 @@ func TestPinAdd(t *testing.T) { t.Error(err) } - p, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p, err := api.Unixfs().Add(ctx, strFile("foo")()) if err != nil { t.Error(err) } @@ -33,7 +33,7 @@ func TestPinSimple(t *testing.T) { t.Error(err) } - p, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p, err := api.Unixfs().Add(ctx, strFile("foo")()) if err != nil { t.Error(err) } @@ -82,12 +82,12 @@ func TestPinRecursive(t *testing.T) { t.Error(err) } - p0, err := api.Unixfs().Add(ctx, strings.NewReader("foo")) + p0, err := api.Unixfs().Add(ctx, strFile("foo")()) if err != nil { t.Error(err) } - p1, err := api.Unixfs().Add(ctx, strings.NewReader("bar")) + p1, err := api.Unixfs().Add(ctx, strFile("bar")()) if err != nil { t.Error(err) } diff --git a/core/coreapi/pubsub.go b/core/coreapi/pubsub.go new file mode 100644 index 000000000..2a8a4c5f0 --- /dev/null +++ b/core/coreapi/pubsub.go @@ -0,0 +1,165 @@ +package coreapi + +import ( + "context" + "errors" + "strings" + "sync" + "time" + + core "github.com/ipfs/go-ipfs/core" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + + cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" + floodsub "gx/ipfs/Qmbi2MdNz6bdqWJg9Fud3WCqTdzP4DXKBwYD16EJVkjzKX/go-libp2p-floodsub" +) + +type PubSubAPI CoreAPI + +type pubSubSubscription struct { + cancel context.CancelFunc + subscription *floodsub.Subscription +} + +type pubSubMessage struct { + msg *floodsub.Message +} + +func (api *PubSubAPI) Ls(ctx context.Context) ([]string, error) { + if err := api.checkNode(); err != nil { + return nil, err + } + + return api.node.Floodsub.GetTopics(), nil +} + +func (api *PubSubAPI) Peers(ctx context.Context, opts ...caopts.PubSubPeersOption) ([]peer.ID, error) { + if err := api.checkNode(); err != nil { + return nil, err + } + + settings, err := caopts.PubSubPeersOptions(opts...) + if err != nil { + return nil, err + } + + peers := api.node.Floodsub.ListPeers(settings.Topic) + out := make([]peer.ID, len(peers)) + + for i, peer := range peers { + out[i] = peer + } + + return out, nil +} + +func (api *PubSubAPI) Publish(ctx context.Context, topic string, data []byte) error { + if err := api.checkNode(); err != nil { + return err + } + + return api.node.Floodsub.Publish(topic, data) +} + +func (api *PubSubAPI) Subscribe(ctx context.Context, topic string, opts ...caopts.PubSubSubscribeOption) (coreiface.PubSubSubscription, error) { + options, err := caopts.PubSubSubscribeOptions(opts...) + + if err := api.checkNode(); err != nil { + return nil, err + } + + sub, err := api.node.Floodsub.Subscribe(topic) + if err != nil { + return nil, err + } + + pubctx, cancel := context.WithCancel(api.node.Context()) + + if options.Discover { + go func() { + blk, err := api.core().Block().Put(pubctx, strings.NewReader("floodsub:"+topic)) + if err != nil { + log.Error("pubsub discovery: ", err) + return + } + + connectToPubSubPeers(pubctx, api.node, blk.Path().Cid()) + }() + } + + return &pubSubSubscription{cancel, sub}, nil +} + +func connectToPubSubPeers(ctx context.Context, n *core.IpfsNode, cid cid.Cid) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + provs := n.Routing.FindProvidersAsync(ctx, cid, 10) + var wg sync.WaitGroup + for p := range provs { + wg.Add(1) + go func(pi pstore.PeerInfo) { + defer wg.Done() + ctx, cancel := context.WithTimeout(ctx, time.Second*10) + defer cancel() + err := n.PeerHost.Connect(ctx, pi) + if err != nil { + log.Info("pubsub discover: ", err) + return + } + log.Info("connected to pubsub peer:", pi.ID) + }(p) + } + + wg.Wait() +} + +func (api *PubSubAPI) checkNode() error { + if !api.node.OnlineMode() { + return coreiface.ErrOffline + } + + if api.node.Floodsub == nil { + return errors.New("experimental pubsub feature not enabled. Run daemon with --enable-pubsub-experiment to use.") + } + + return nil +} + +func (sub *pubSubSubscription) Close() error { + sub.cancel() + sub.subscription.Cancel() + return nil +} + +func (sub *pubSubSubscription) Next(ctx context.Context) (coreiface.PubSubMessage, error) { + msg, err := sub.subscription.Next(ctx) + if err != nil { + return nil, err + } + + return &pubSubMessage{msg}, nil +} + +func (msg *pubSubMessage) From() peer.ID { + return peer.ID(msg.msg.From) +} + +func (msg *pubSubMessage) Data() []byte { + return msg.msg.Data +} + +func (msg *pubSubMessage) Seq() []byte { + return msg.msg.Seqno +} + +func (msg *pubSubMessage) Topics() []string { + return msg.msg.TopicIDs +} + +func (api *PubSubAPI) core() coreiface.CoreAPI { + return (*CoreAPI)(api) +} diff --git a/core/coreapi/pubsub_test.go b/core/coreapi/pubsub_test.go new file mode 100644 index 000000000..11a8c68a5 --- /dev/null +++ b/core/coreapi/pubsub_test.go @@ -0,0 +1,96 @@ +package coreapi_test + +import ( + "context" + "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + "testing" + "time" +) + +func TestBasicPubSub(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + nds, apis, err := makeAPISwarm(ctx, true, 2) + if err != nil { + t.Fatal(err) + } + + sub, err := apis[0].PubSub().Subscribe(ctx, "testch") + if err != nil { + t.Fatal(err) + } + + go func() { + tick := time.Tick(100 * time.Millisecond) + + for { + err = apis[1].PubSub().Publish(ctx, "testch", []byte("hello world")) + if err != nil { + t.Fatal(err) + } + select { + case <-tick: + case <-ctx.Done(): + return + } + } + }() + + m, err := sub.Next(ctx) + if err != nil { + t.Fatal(err) + } + + if string(m.Data()) != "hello world" { + t.Errorf("got invalid data: %s", string(m.Data())) + } + + if m.From() != nds[1].Identity { + t.Errorf("m.From didn't match") + } + + peers, err := apis[1].PubSub().Peers(ctx, options.PubSub.Topic("testch")) + if err != nil { + t.Fatal(err) + } + + if len(peers) != 1 { + t.Fatalf("got incorrect number of peers: %d", len(peers)) + } + + if peers[0] != nds[0].Identity { + t.Errorf("peer didn't match") + } + + peers, err = apis[1].PubSub().Peers(ctx, options.PubSub.Topic("nottestch")) + if err != nil { + t.Fatal(err) + } + + if len(peers) != 0 { + t.Fatalf("got incorrect number of peers: %d", len(peers)) + } + + topics, err := apis[0].PubSub().Ls(ctx) + if err != nil { + t.Fatal(err) + } + + if len(topics) != 1 { + t.Fatalf("got incorrect number of topics: %d", len(peers)) + } + + if topics[0] != "testch" { + t.Errorf("topic didn't match") + } + + topics, err = apis[1].PubSub().Ls(ctx) + if err != nil { + t.Fatal(err) + } + + if len(topics) != 0 { + t.Fatalf("got incorrect number of topics: %d", len(peers)) + } +} diff --git a/core/coreapi/swarm.go b/core/coreapi/swarm.go new file mode 100644 index 000000000..1c67bc34e --- /dev/null +++ b/core/coreapi/swarm.go @@ -0,0 +1,175 @@ +package coreapi + +import ( + "context" + "sort" + "time" + + core "github.com/ipfs/go-ipfs/core" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" + + inet "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + net "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" + protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" + swarm "gx/ipfs/Qmb55o5PuhvqwjdVLvc4VV3ouLziYc6TfwM9LC6GwBQokn/go-libp2p-swarm" + peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" + iaddr "gx/ipfs/QmesXvbRGyKQn1XbPHx1Mr5E6RTJYR9c8zwFVuGZq9Aa1j/go-ipfs-addr" +) + +type SwarmAPI CoreAPI + +type connInfo struct { + node *core.IpfsNode + conn net.Conn + dir net.Direction + + addr ma.Multiaddr + peer peer.ID + muxer string +} + +func (api *SwarmAPI) Connect(ctx context.Context, pi pstore.PeerInfo) error { + if api.node.PeerHost == nil { + return coreiface.ErrOffline + } + + if swrm, ok := api.node.PeerHost.Network().(*swarm.Swarm); ok { + swrm.Backoff().Clear(pi.ID) + } + + return api.node.PeerHost.Connect(ctx, pi) +} + +func (api *SwarmAPI) Disconnect(ctx context.Context, addr ma.Multiaddr) error { + if api.node.PeerHost == nil { + return coreiface.ErrOffline + } + + ia, err := iaddr.ParseMultiaddr(ma.Multiaddr(addr)) + if err != nil { + return err + } + + taddr := ia.Transport() + id := ia.ID() + net := api.node.PeerHost.Network() + + if taddr == nil { + if net.Connectedness(id) != inet.Connected { + return coreiface.ErrNotConnected + } else if err := net.ClosePeer(id); err != nil { + return err + } + } else { + for _, conn := range net.ConnsToPeer(id) { + if !conn.RemoteMultiaddr().Equal(taddr) { + continue + } + + return conn.Close() + } + + return coreiface.ErrConnNotFound + } + + return nil +} + +func (api *SwarmAPI) KnownAddrs(context.Context) (map[peer.ID][]ma.Multiaddr, error) { + if api.node.PeerHost == nil { + return nil, coreiface.ErrOffline + } + + addrs := make(map[peer.ID][]ma.Multiaddr) + ps := api.node.PeerHost.Network().Peerstore() + for _, p := range ps.Peers() { + for _, a := range ps.Addrs(p) { + addrs[p] = append(addrs[p], a) + } + sort.Slice(addrs[p], func(i, j int) bool { + return addrs[p][i].String() < addrs[p][j].String() + }) + } + + return addrs, nil +} + +func (api *SwarmAPI) LocalAddrs(context.Context) ([]ma.Multiaddr, error) { + if api.node.PeerHost == nil { + return nil, coreiface.ErrOffline + } + + return api.node.PeerHost.Addrs(), nil +} + +func (api *SwarmAPI) ListenAddrs(context.Context) ([]ma.Multiaddr, error) { + if api.node.PeerHost == nil { + return nil, coreiface.ErrOffline + } + + return api.node.PeerHost.Network().InterfaceListenAddresses() +} + +func (api *SwarmAPI) Peers(context.Context) ([]coreiface.ConnectionInfo, error) { + if api.node.PeerHost == nil { + return nil, coreiface.ErrOffline + } + + conns := api.node.PeerHost.Network().Conns() + + var out []coreiface.ConnectionInfo + for _, c := range conns { + pid := c.RemotePeer() + addr := c.RemoteMultiaddr() + + ci := &connInfo{ + node: api.node, + conn: c, + dir: c.Stat().Direction, + + addr: addr, + peer: pid, + } + + /* + // FIXME(steb): + swcon, ok := c.(*swarm.Conn) + if ok { + ci.muxer = fmt.Sprintf("%T", swcon.StreamConn().Conn()) + } + */ + + out = append(out, ci) + } + + return out, nil +} + +func (ci *connInfo) ID() peer.ID { + return ci.peer +} + +func (ci *connInfo) Address() ma.Multiaddr { + return ci.addr +} + +func (ci *connInfo) Direction() net.Direction { + return ci.dir +} + +func (ci *connInfo) Latency() (time.Duration, error) { + return ci.node.Peerstore.LatencyEWMA(peer.ID(ci.ID())), nil +} + +func (ci *connInfo) Streams() ([]protocol.ID, error) { + streams := ci.conn.GetStreams() + + out := make([]protocol.ID, len(streams)) + for i, s := range streams { + out[i] = s.Protocol() + } + + return out, nil +} diff --git a/core/coreapi/unixfile.go b/core/coreapi/unixfile.go new file mode 100644 index 000000000..00fe0ed02 --- /dev/null +++ b/core/coreapi/unixfile.go @@ -0,0 +1,190 @@ +package coreapi + +import ( + "context" + "errors" + "io" + "os" + gopath "path" + "time" + + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" +) + +// Number to file to prefetch in directories +// TODO: should we allow setting this via context hint? +const prefetchFiles = 4 + +// TODO: this probably belongs in go-unixfs (and could probably replace a chunk of it's interface in the long run) + +type sizeInfo struct { + size int64 + name string + modTime time.Time +} + +func (s *sizeInfo) Name() string { + return s.name +} + +func (s *sizeInfo) Size() int64 { + return s.size +} + +func (s *sizeInfo) Mode() os.FileMode { + return 0444 // all read +} + +func (s *sizeInfo) ModTime() time.Time { + return s.modTime +} + +func (s *sizeInfo) IsDir() bool { + return false +} + +func (s *sizeInfo) Sys() interface{} { + return nil +} + +type ufsDirectory struct { + ctx context.Context + dserv ipld.DAGService + + files chan *ipld.Link + + name string + path string +} + +func (d *ufsDirectory) Close() error { + return files.ErrNotReader +} + +func (d *ufsDirectory) Read(_ []byte) (int, error) { + return 0, files.ErrNotReader +} + +func (d *ufsDirectory) FileName() string { + return d.name +} + +func (d *ufsDirectory) FullPath() string { + return d.path +} + +func (d *ufsDirectory) IsDirectory() bool { + return true +} + +func (d *ufsDirectory) NextFile() (files.File, error) { + l, ok := <-d.files + if !ok { + return nil, io.EOF + } + + nd, err := l.GetNode(d.ctx, d.dserv) + if err != nil { + return nil, err + } + + return newUnixfsFile(d.ctx, d.dserv, nd, l.Name, d) +} + +type ufsFile struct { + uio.DagReader + + name string + path string +} + +func (f *ufsFile) IsDirectory() bool { + return false +} + +func (f *ufsFile) NextFile() (files.File, error) { + return nil, files.ErrNotDirectory +} + +func (f *ufsFile) FileName() string { + return f.name +} + +func (f *ufsFile) FullPath() string { + return f.path +} + +func (f *ufsFile) Size() (int64, error) { + return int64(f.DagReader.Size()), nil +} + +func newUnixfsDir(ctx context.Context, dserv ipld.DAGService, nd ipld.Node, name string, path string) (files.File, error) { + dir, err := uio.NewDirectoryFromNode(dserv, nd) + if err != nil { + return nil, err + } + + fileCh := make(chan *ipld.Link, prefetchFiles) + go func() { + dir.ForEachLink(ctx, func(link *ipld.Link) error { + select { + case fileCh <- link: + case <-ctx.Done(): + return ctx.Err() + } + return nil + }) + + close(fileCh) + }() + + return &ufsDirectory{ + ctx: ctx, + dserv: dserv, + + files: fileCh, + + name: name, + path: path, + }, nil +} + +func newUnixfsFile(ctx context.Context, dserv ipld.DAGService, nd ipld.Node, name string, parent files.File) (files.File, error) { + path := name + if parent != nil { + path = gopath.Join(parent.FullPath(), name) + } + + switch dn := nd.(type) { + case *dag.ProtoNode: + fsn, err := ft.FSNodeFromBytes(dn.Data()) + if err != nil { + return nil, err + } + if fsn.IsDir() { + return newUnixfsDir(ctx, dserv, nd, name, path) + } + + case *dag.RawNode: + default: + return nil, errors.New("unknown node type") + } + + dr, err := uio.NewDagReader(ctx, nd, dserv) + if err != nil { + return nil, err + } + + return &ufsFile{ + DagReader: dr, + + name: name, + path: path, + }, nil +} + +var _ os.FileInfo = &sizeInfo{} diff --git a/core/coreapi/unixfs.go b/core/coreapi/unixfs.go index 1a2479ab9..f023bb151 100644 --- a/core/coreapi/unixfs.go +++ b/core/coreapi/unixfs.go @@ -2,13 +2,24 @@ package coreapi import ( "context" - "io" + "fmt" + "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/filestore" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - coreunix "github.com/ipfs/go-ipfs/core/coreunix" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" + "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + "github.com/ipfs/go-ipfs/core/coreunix" - cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + dagtest "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag/test" + blockservice "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -16,16 +27,118 @@ type UnixfsAPI CoreAPI // Add builds a merkledag node from a reader, adds it to the blockstore, // and returns the key representing that node. -func (api *UnixfsAPI) Add(ctx context.Context, r io.Reader) (coreiface.ResolvedPath, error) { - k, err := coreunix.AddWithContext(ctx, api.node, r) +func (api *UnixfsAPI) Add(ctx context.Context, files files.File, opts ...options.UnixfsAddOption) (coreiface.ResolvedPath, error) { + settings, prefix, err := options.UnixfsAddOptions(opts...) if err != nil { return nil, err } - c, err := cid.Decode(k) + + n := api.node + + cfg, err := n.Repo.Config() if err != nil { return nil, err } - return coreiface.IpfsPath(c), nil + + // check if repo will exceed storage limit if added + // TODO: this doesn't handle the case if the hashed file is already in blocks (deduplicated) + // TODO: conditional GC is disabled due to it is somehow not possible to pass the size to the daemon + //if err := corerepo.ConditionalGC(req.Context(), n, uint64(size)); err != nil { + // res.SetError(err, cmdkit.ErrNormal) + // return + //} + + if settings.NoCopy && !cfg.Experimental.FilestoreEnabled { + return nil, filestore.ErrFilestoreNotEnabled + } + + if settings.OnlyHash { + nilnode, err := core.NewNode(ctx, &core.BuildCfg{ + //TODO: need this to be true or all files + // hashed will be stored in memory! + NilRepo: true, + }) + if err != nil { + return nil, err + } + n = nilnode + } + + addblockstore := n.Blockstore + if !(settings.FsCache || settings.NoCopy) { + addblockstore = bstore.NewGCBlockstore(n.BaseBlocks, n.GCLocker) + } + + exch := n.Exchange + if settings.Local { + exch = offline.Exchange(addblockstore) + } + + bserv := blockservice.New(addblockstore, exch) // hash security 001 + dserv := dag.NewDAGService(bserv) + + fileAdder, err := coreunix.NewAdder(ctx, n.Pinning, n.Blockstore, dserv) + if err != nil { + return nil, err + } + + fileAdder.Chunker = settings.Chunker + if settings.Events != nil { + fileAdder.Out = settings.Events + fileAdder.Progress = settings.Progress + } + fileAdder.Hidden = settings.Hidden + fileAdder.Wrap = settings.Wrap + fileAdder.Pin = settings.Pin && !settings.OnlyHash + fileAdder.Silent = settings.Silent + fileAdder.RawLeaves = settings.RawLeaves + fileAdder.NoCopy = settings.NoCopy + fileAdder.Name = settings.StdinName + fileAdder.CidBuilder = prefix + + switch settings.Layout { + case options.BalancedLayout: + // Default + case options.TrickleLayout: + fileAdder.Trickle = true + default: + return nil, fmt.Errorf("unknown layout: %d", settings.Layout) + } + + if settings.Inline { + fileAdder.CidBuilder = cidutil.InlineBuilder{ + Builder: fileAdder.CidBuilder, + Limit: settings.InlineLimit, + } + } + + if settings.OnlyHash { + md := dagtest.Mock() + emptyDirNode := ft.EmptyDirNode() + // Use the same prefix for the "empty" MFS root as for the file adder. + emptyDirNode.SetCidBuilder(fileAdder.CidBuilder) + mr, err := mfs.NewRoot(ctx, md, emptyDirNode, nil) + if err != nil { + return nil, err + } + + fileAdder.SetMfsRoot(mr) + } + + nd, err := fileAdder.AddAllAndPin(files) + if err != nil { + return nil, err + } + return coreiface.IpfsPath(nd.Cid()), nil +} + +func (api *UnixfsAPI) Get(ctx context.Context, p coreiface.Path) (files.File, error) { + nd, err := api.core().ResolveNode(ctx, p) + if err != nil { + return nil, err + } + + return newUnixfsFile(ctx, api.node.DAG, nd, "", nil) } // Cat returns the data contained by an IPFS or IPNS object(s) at path `p`. diff --git a/core/coreapi/unixfs_test.go b/core/coreapi/unixfs_test.go index bc78448f5..caf598340 100644 --- a/core/coreapi/unixfs_test.go +++ b/core/coreapi/unixfs_test.go @@ -6,29 +6,35 @@ import ( "encoding/base64" "fmt" "io" + "io/ioutil" "math" + "os" + "strconv" "strings" + "sync" "testing" - core "github.com/ipfs/go-ipfs/core" - coreapi "github.com/ipfs/go-ipfs/core/coreapi" + "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" - options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" - coreunix "github.com/ipfs/go-ipfs/core/coreunix" + "github.com/ipfs/go-ipfs/core/coreapi/interface/options" + "github.com/ipfs/go-ipfs/core/coreunix" mock "github.com/ipfs/go-ipfs/core/mock" - keystore "github.com/ipfs/go-ipfs/keystore" - repo "github.com/ipfs/go-ipfs/repo" + "github.com/ipfs/go-ipfs/keystore" + "github.com/ipfs/go-ipfs/repo" + mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" + unixfs "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" cbor "gx/ipfs/QmSywXfm2v4Qkp4DcFqo8eehj49dJK3bdUnaLVxrdFLMQn/go-ipld-cbor" - unixfs "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + mdag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - mdag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe" @@ -88,6 +94,9 @@ func makeAPISwarm(ctx context.Context, fullIdentity bool, n int) ([]*core.IpfsNo Repo: r, Host: mock.MockHostOption(mn), Online: fullIdentity, + ExtraOpts: map[string]bool{ + "pubsub": true, + }, }) if err != nil { return nil, nil, err @@ -125,6 +134,37 @@ func makeAPI(ctx context.Context) (*core.IpfsNode, coreiface.CoreAPI, error) { return nd[0], api[0], nil } +func strFile(data string) func() files.File { + return func() files.File { + return files.NewReaderFile("", "", ioutil.NopCloser(strings.NewReader(data)), nil) + } +} + +func twoLevelDir() func() files.File { + return func() files.File { + return files.NewSliceFile("t", "t", []files.File{ + files.NewSliceFile("t/abc", "t/abc", []files.File{ + files.NewReaderFile("t/abc/def", "t/abc/def", ioutil.NopCloser(strings.NewReader("world")), nil), + }), + files.NewReaderFile("t/bar", "t/bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/foo", "t/foo", ioutil.NopCloser(strings.NewReader("hello1")), nil), + }) + } +} + +func flatDir() files.File { + return files.NewSliceFile("t", "t", []files.File{ + files.NewReaderFile("t/bar", "t/bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/foo", "t/foo", ioutil.NopCloser(strings.NewReader("hello1")), nil), + }) +} + +func wrapped(f files.File) files.File { + return files.NewSliceFile("", "", []files.File{ + f, + }) +} + func TestAdd(t *testing.T) { ctx := context.Background() _, api, err := makeAPI(ctx) @@ -132,84 +172,454 @@ func TestAdd(t *testing.T) { t.Error(err) } - str := strings.NewReader(helloStr) - p, err := api.Unixfs().Add(ctx, str) - if err != nil { - t.Error(err) + cases := []struct { + name string + data func() files.File + expect func(files.File) files.File + + path string + err string + + recursive bool + + events []coreiface.AddEvent + + opts []options.UnixfsAddOption + }{ + // Simple cases + { + name: "simpleAdd", + data: strFile(helloStr), + path: hello, + opts: []options.UnixfsAddOption{}, + }, + { + name: "addEmpty", + data: strFile(""), + path: emptyFile, + }, + // CIDv1 version / rawLeaves + { + name: "addCidV1", + data: strFile(helloStr), + path: "/ipfs/zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd", + opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(1)}, + }, + { + name: "addCidV1NoLeaves", + data: strFile(helloStr), + path: "/ipfs/zdj7WY4GbN8NDbTW1dfCShAQNVovams2xhq9hVCx5vXcjvT8g", + opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(1), options.Unixfs.RawLeaves(false)}, + }, + // Non sha256 hash vs CID + { + name: "addCidSha3", + data: strFile(helloStr), + path: "/ipfs/zb2wwnYtXBxpndNABjtYxWAPt3cwWNRnc11iT63fvkYV78iRb", + opts: []options.UnixfsAddOption{options.Unixfs.Hash(mh.SHA3_256)}, + }, + { + name: "addCidSha3Cid0", + data: strFile(helloStr), + err: "CIDv0 only supports sha2-256", + opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(0), options.Unixfs.Hash(mh.SHA3_256)}, + }, + // Inline + { + name: "addInline", + data: strFile(helloStr), + path: "/ipfs/zaYomJdLndMku8P9LHngHB5w2CQ7NenLbv", + opts: []options.UnixfsAddOption{options.Unixfs.Inline(true)}, + }, + { + name: "addInlineLimit", + data: strFile(helloStr), + path: "/ipfs/zaYomJdLndMku8P9LHngHB5w2CQ7NenLbv", + opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(32), options.Unixfs.Inline(true)}, + }, + { + name: "addInlineZero", + data: strFile(""), + path: "/ipfs/z2yYDV", + opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(0), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true)}, + }, + { //TODO: after coreapi add is used in `ipfs add`, consider making this default for inline + name: "addInlineRaw", + data: strFile(helloStr), + path: "/ipfs/zj7Gr8AcBreqGEfrnR5kPFe", + opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(32), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true)}, + }, + // Chunker / Layout + { + name: "addChunks", + data: strFile(strings.Repeat("aoeuidhtns", 200)), + path: "/ipfs/QmRo11d4QJrST47aaiGVJYwPhoNA4ihRpJ5WaxBWjWDwbX", + opts: []options.UnixfsAddOption{options.Unixfs.Chunker("size-4")}, + }, + { + name: "addChunksTrickle", + data: strFile(strings.Repeat("aoeuidhtns", 200)), + path: "/ipfs/QmNNhDGttafX3M1wKWixGre6PrLFGjnoPEDXjBYpTv93HP", + opts: []options.UnixfsAddOption{options.Unixfs.Chunker("size-4"), options.Unixfs.Layout(options.TrickleLayout)}, + }, + // Local + { + name: "addLocal", // better cases in sharness + data: strFile(helloStr), + path: hello, + opts: []options.UnixfsAddOption{options.Unixfs.Local(true)}, + }, + { + name: "hashOnly", // test (non)fetchability + data: strFile(helloStr), + path: hello, + opts: []options.UnixfsAddOption{options.Unixfs.HashOnly(true)}, + }, + // multi file + { + name: "simpleDir", + data: flatDir, + recursive: true, + path: "/ipfs/QmRKGpFfR32FVXdvJiHfo4WJ5TDYBsM1P9raAp1p6APWSp", + }, + { + name: "twoLevelDir", + data: twoLevelDir(), + recursive: true, + path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr", + }, + // wrapped + { + name: "addWrapped", + path: "/ipfs/QmVE9rNpj5doj7XHzp5zMUxD7BJgXEqx4pe3xZ3JBReWHE", + data: func() files.File { + return files.NewReaderFile("foo", "foo", ioutil.NopCloser(strings.NewReader(helloStr)), nil) + }, + expect: wrapped, + opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)}, + }, + { + name: "stdinWrapped", + path: "/ipfs/QmU3r81oZycjHS9oaSHw37ootMFuFUw1DvMLKXPsezdtqU", + data: func() files.File { + return files.NewReaderFile("", os.Stdin.Name(), ioutil.NopCloser(strings.NewReader(helloStr)), nil) + }, + expect: func(files.File) files.File { + return files.NewSliceFile("", "", []files.File{ + files.NewReaderFile("QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk", "QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk", ioutil.NopCloser(strings.NewReader(helloStr)), nil), + }) + }, + opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)}, + }, + { + name: "stdinNamed", + path: "/ipfs/QmQ6cGBmb3ZbdrQW1MRm1RJnYnaxCqfssz7CrTa9NEhQyS", + data: func() files.File { + return files.NewReaderFile("", os.Stdin.Name(), ioutil.NopCloser(strings.NewReader(helloStr)), nil) + }, + expect: func(files.File) files.File { + return files.NewSliceFile("", "", []files.File{ + files.NewReaderFile("test", "test", ioutil.NopCloser(strings.NewReader(helloStr)), nil), + }) + }, + opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true), options.Unixfs.StdinName("test")}, + }, + { + name: "twoLevelDirWrapped", + data: twoLevelDir(), + recursive: true, + expect: wrapped, + path: "/ipfs/QmPwsL3T5sWhDmmAWZHAzyjKtMVDS9a11aHNRqb3xoVnmg", + opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)}, + }, + { + name: "twoLevelInlineHash", + data: twoLevelDir(), + recursive: true, + expect: wrapped, + path: "/ipfs/zBunoruKoyCHKkALNSWxDvj4L7yuQnMgQ4hUa9j1Z64tVcDEcu6Zdetyu7eeFCxMPfxb7YJvHeFHoFoHMkBUQf6vfdhmi", + opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true), options.Unixfs.Hash(mh.SHA3)}, + }, + // hidden + { + name: "hiddenFiles", + data: func() files.File { + return files.NewSliceFile("t", "t", []files.File{ + files.NewReaderFile("t/.bar", "t/.bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/bar", "t/bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/foo", "t/foo", ioutil.NopCloser(strings.NewReader("hello1")), nil), + }) + }, + recursive: true, + path: "/ipfs/QmehGvpf2hY196MzDFmjL8Wy27S4jbgGDUAhBJyvXAwr3g", + opts: []options.UnixfsAddOption{options.Unixfs.Hidden(true)}, + }, + { + name: "hiddenFileAlwaysAdded", + data: func() files.File { + return files.NewReaderFile(".foo", ".foo", ioutil.NopCloser(strings.NewReader(helloStr)), nil) + }, + recursive: true, + path: hello, + }, + { + name: "hiddenFilesNotAdded", + data: func() files.File { + return files.NewSliceFile("t", "t", []files.File{ + files.NewReaderFile("t/.bar", "t/.bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/bar", "t/bar", ioutil.NopCloser(strings.NewReader("hello2")), nil), + files.NewReaderFile("t/foo", "t/foo", ioutil.NopCloser(strings.NewReader("hello1")), nil), + }) + }, + expect: func(files.File) files.File { + return flatDir() + }, + recursive: true, + path: "/ipfs/QmRKGpFfR32FVXdvJiHfo4WJ5TDYBsM1P9raAp1p6APWSp", + opts: []options.UnixfsAddOption{options.Unixfs.Hidden(false)}, + }, + // Events / Progress + { + name: "simpleAddEvent", + data: strFile(helloStr), + path: "/ipfs/zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd", + events: []coreiface.AddEvent{ + {Name: "zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd", Hash: "zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd", Size: strconv.Itoa(len(helloStr))}, + }, + opts: []options.UnixfsAddOption{options.Unixfs.RawLeaves(true)}, + }, + { + name: "silentAddEvent", + data: twoLevelDir(), + path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr", + events: []coreiface.AddEvent{ + {Name: "t/abc", Hash: "QmU7nuGs2djqK99UNsNgEPGh6GV4662p6WtsgccBNGTDxt", Size: "62"}, + {Name: "t", Hash: "QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr", Size: "229"}, + }, + recursive: true, + opts: []options.UnixfsAddOption{options.Unixfs.Silent(true)}, + }, + { + name: "dirAddEvents", + data: twoLevelDir(), + path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr", + events: []coreiface.AddEvent{ + {Name: "t/abc/def", Hash: "QmNyJpQkU1cEkBwMDhDNFstr42q55mqG5GE5Mgwug4xyGk", Size: "13"}, + {Name: "t/bar", Hash: "QmS21GuXiRMvJKHos4ZkEmQDmRBqRaF5tQS2CQCu2ne9sY", Size: "14"}, + {Name: "t/foo", Hash: "QmfAjGiVpTN56TXi6SBQtstit5BEw3sijKj1Qkxn6EXKzJ", Size: "14"}, + {Name: "t/abc", Hash: "QmU7nuGs2djqK99UNsNgEPGh6GV4662p6WtsgccBNGTDxt", Size: "62"}, + {Name: "t", Hash: "QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr", Size: "229"}, + }, + recursive: true, + }, + { + name: "progress1M", + data: func() files.File { + r := bytes.NewReader(bytes.Repeat([]byte{0}, 1000000)) + return files.NewReaderFile("", "", ioutil.NopCloser(r), nil) + }, + path: "/ipfs/QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD", + events: []coreiface.AddEvent{ + {Name: "", Bytes: 262144}, + {Name: "", Bytes: 524288}, + {Name: "", Bytes: 786432}, + {Name: "", Bytes: 1000000}, + {Name: "QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD", Hash: "QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD", Size: "1000256"}, + }, + recursive: true, + opts: []options.UnixfsAddOption{options.Unixfs.Progress(true)}, + }, } - if p.String() != hello { - t.Fatalf("expected path %s, got: %s", hello, p) - } + for _, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() - r, err := api.Unixfs().Cat(ctx, p) - if err != nil { - t.Fatal(err) - } - buf := make([]byte, len(helloStr)) - _, err = io.ReadFull(r, buf) - if err != nil { - t.Error(err) - } + // recursive logic - if string(buf) != helloStr { - t.Fatalf("expected [%s], got [%s] [err=%s]", helloStr, string(buf), err) + data := testCase.data() + if testCase.recursive { + data = files.NewSliceFile("", "", []files.File{ + data, + }) + } + + // handle events if relevant to test case + + opts := testCase.opts + eventOut := make(chan interface{}) + var evtWg sync.WaitGroup + if len(testCase.events) > 0 { + opts = append(opts, options.Unixfs.Events(eventOut)) + evtWg.Add(1) + + go func() { + defer evtWg.Done() + expected := testCase.events + + for evt := range eventOut { + event, ok := evt.(*coreiface.AddEvent) + if !ok { + t.Fatal("unexpected event type") + } + + if len(expected) < 1 { + t.Fatal("got more events than expected") + } + + if expected[0].Size != event.Size { + t.Errorf("Event.Size didn't match, %s != %s", expected[0].Size, event.Size) + } + + if expected[0].Name != event.Name { + t.Errorf("Event.Name didn't match, %s != %s", expected[0].Name, event.Name) + } + + if expected[0].Hash != event.Hash { + t.Errorf("Event.Hash didn't match, %s != %s", expected[0].Hash, event.Hash) + } + if expected[0].Bytes != event.Bytes { + t.Errorf("Event.Bytes didn't match, %d != %d", expected[0].Bytes, event.Bytes) + } + + expected = expected[1:] + } + + if len(expected) > 0 { + t.Fatalf("%d event(s) didn't arrive", len(expected)) + } + }() + } + + // Add! + + p, err := api.Unixfs().Add(ctx, data, opts...) + close(eventOut) + evtWg.Wait() + if testCase.err != "" { + if err == nil { + t.Fatalf("expected an error: %s", testCase.err) + } + if err.Error() != testCase.err { + t.Fatalf("expected an error: '%s' != '%s'", err.Error(), testCase.err) + } + return + } + if err != nil { + t.Fatal(err) + } + + if p.String() != testCase.path { + t.Errorf("expected path %s, got: %s", testCase.path, p) + } + + // compare file structure with Unixfs().Get + + var cmpFile func(orig files.File, got files.File) + cmpFile = func(orig files.File, got files.File) { + if orig.IsDirectory() != got.IsDirectory() { + t.Fatal("file type mismatch") + } + + if !orig.IsDirectory() { + defer orig.Close() + defer got.Close() + + do, err := ioutil.ReadAll(orig) + if err != nil { + t.Fatal(err) + } + + dg, err := ioutil.ReadAll(got) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(do, dg) { + t.Fatal("data not equal") + } + + return + } + + for { + fo, err := orig.NextFile() + fg, err2 := got.NextFile() + + if err != nil { + if err == io.EOF && err2 == io.EOF { + break + } + t.Fatal(err) + } + if err2 != nil { + t.Fatal(err) + } + + cmpFile(fo, fg) + } + } + + f, err := api.Unixfs().Get(ctx, p) + if err != nil { + t.Fatal(err) + } + + orig := testCase.data() + if testCase.expect != nil { + orig = testCase.expect(orig) + } + + cmpFile(orig, f) + }) } } -func TestAddEmptyFile(t *testing.T) { +func TestAddPinned(t *testing.T) { ctx := context.Background() _, api, err := makeAPI(ctx) if err != nil { t.Error(err) } - str := strings.NewReader("") - p, err := api.Unixfs().Add(ctx, str) + _, err = api.Unixfs().Add(ctx, strFile(helloStr)(), options.Unixfs.Pin(true)) if err != nil { t.Error(err) } - if p.String() != emptyFile { - t.Fatalf("expected path %s, got: %s", hello, p) + pins, err := api.Pin().Ls(ctx) + if len(pins) != 1 { + t.Fatalf("expected 1 pin, got %d", len(pins)) + } + + if pins[0].Path().String() != "/ipld/QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk" { + t.Fatalf("got unexpected pin: %s", pins[0].Path().String()) } } -func TestCatBasic(t *testing.T) { +func TestAddHashOnly(t *testing.T) { ctx := context.Background() - node, api, err := makeAPI(ctx) - if err != nil { - t.Fatal(err) - } - - hr := strings.NewReader(helloStr) - p, err := coreunix.Add(node, hr) - if err != nil { - t.Fatal(err) - } - p = "/ipfs/" + p - - if p != hello { - t.Fatalf("expected CID %s, got: %s", hello, p) - } - - helloPath, err := coreiface.ParsePath(hello) - if err != nil { - t.Fatal(err) - } - - r, err := api.Unixfs().Cat(ctx, helloPath) - if err != nil { - t.Fatal(err) - } - - buf := make([]byte, len(helloStr)) - _, err = io.ReadFull(r, buf) + _, api, err := makeAPI(ctx) if err != nil { t.Error(err) } - if string(buf) != helloStr { - t.Fatalf("expected [%s], got [%s] [err=%s]", helloStr, string(buf), err) + + p, err := api.Unixfs().Add(ctx, strFile(helloStr)(), options.Unixfs.HashOnly(true)) + if err != nil { + t.Error(err) + } + + if p.String() != hello { + t.Errorf("unxepected path: %s", p.String()) + } + + _, err = api.Block().Get(ctx, p) + if err == nil { + t.Fatal("expected an error") + } + if err.Error() != "blockservice: key not found" { + t.Errorf("unxepected error: %s", err.Error()) } } diff --git a/core/coredag/dagpb.go b/core/coredag/dagpb.go index f91fe6406..62b3ea332 100644 --- a/core/coredag/dagpb.go +++ b/core/coredag/dagpb.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "math" - "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" diff --git a/core/coredag/raw.go b/core/coredag/raw.go index cd6a62f1a..033f0d44d 100644 --- a/core/coredag/raw.go +++ b/core/coredag/raw.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "math" - "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" diff --git a/core/corehttp/commands.go b/core/corehttp/commands.go index 5cd6670e2..d98469ee3 100644 --- a/core/corehttp/commands.go +++ b/core/corehttp/commands.go @@ -14,10 +14,10 @@ import ( "github.com/ipfs/go-ipfs/core" corecommands "github.com/ipfs/go-ipfs/core/commands" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" cmds "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds" cmdsHttp "gx/ipfs/QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz/go-ipfs-cmds/http" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) var ( diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index eaba8fc3f..3ab6dcde3 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -9,7 +9,7 @@ import ( core "github.com/ipfs/go-ipfs/core" coreapi "github.com/ipfs/go-ipfs/core/coreapi" - id "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/protocol/identify" + id "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/protocol/identify" ) type GatewayConfig struct { diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 9e0b8e1ec..00631df41 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net/http" "net/url" "os" @@ -16,17 +17,18 @@ import ( core "github.com/ipfs/go-ipfs/core" coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/dagutils" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + resolver "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path/resolver" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" + files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + chunker "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" multibase "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase" ) @@ -266,7 +268,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr w.Header().Set("Content-Disposition", fmt.Sprintf("inline; filename*=UTF-8''%s", url.PathEscape(urlFilename))) name = urlFilename } else { - name = gopath.Base(urlPath) + name = getFilename(urlPath) } i.serveFile(w, r, name, modtime, dr) return @@ -398,7 +400,7 @@ func (i *gatewayHandler) serveFile(w http.ResponseWriter, req *http.Request, nam } func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) { - p, err := i.api.Unixfs().Add(ctx, r.Body) + p, err := i.api.Unixfs().Add(ctx, files.NewReaderFile("", "", ioutil.NopCloser(r.Body), nil)) if err != nil { internalWebError(w, err) return @@ -624,3 +626,11 @@ func webErrorWithCode(w http.ResponseWriter, message string, err error, code int func internalWebError(w http.ResponseWriter, err error) { webErrorWithCode(w, "internalWebError", err, http.StatusInternalServerError) } + +func getFilename(s string) string { + if (strings.HasPrefix(s, ipfsPathPrefix) || strings.HasPrefix(s, ipnsPathPrefix)) && strings.Count(gopath.Clean(s), "/") <= 2 { + // Don't want to treat ipfs.io in /ipns/ipfs.io as a filename. + return "" + } + return gopath.Base(s) +} diff --git a/core/corehttp/gateway_test.go b/core/corehttp/gateway_test.go index f93c8844c..609db1ffe 100644 --- a/core/corehttp/gateway_test.go +++ b/core/corehttp/gateway_test.go @@ -19,12 +19,12 @@ import ( repo "github.com/ipfs/go-ipfs/repo" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - id "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/protocol/identify" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + id "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/protocol/identify" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" ) // `ipfs object new unixfs-dir` @@ -161,6 +161,14 @@ func TestGatewayGet(t *testing.T) { ns["/ipns/double.example.com"] = path.FromString("/ipns/working.example.com") ns["/ipns/triple.example.com"] = path.FromString("/ipns/double.example.com") ns["/ipns/broken.example.com"] = path.FromString("/ipns/" + k) + // We picked .man because: + // 1. It's a valid TLD. + // 2. Go treats it as the file extension for "man" files (even though + // nobody actually *uses* this extension, AFAIK). + // + // Unfortunately, this may not work on all platforms as file type + // detection is platform dependent. + ns["/ipns/example.man"] = path.FromString("/ipfs/" + k) t.Log(ts.URL) for _, test := range []struct { @@ -183,6 +191,8 @@ func TestGatewayGet(t *testing.T) { {"working.example.com", "/ipfs/" + k, http.StatusNotFound, "ipfs resolve -r /ipns/working.example.com/ipfs/" + k + ": no link by that name\n"}, {"broken.example.com", "/", http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com/: " + namesys.ErrResolveFailed.Error() + "\n"}, {"broken.example.com", "/ipfs/" + k, http.StatusNotFound, "ipfs resolve -r /ipns/broken.example.com/ipfs/" + k + ": " + namesys.ErrResolveFailed.Error() + "\n"}, + // This test case ensures we don't treat the TLD as a file extension. + {"example.man", "/", http.StatusOK, "fnord"}, } { var c http.Client r, err := http.NewRequest("GET", ts.URL+test.path, nil) @@ -198,6 +208,10 @@ func TestGatewayGet(t *testing.T) { continue } defer resp.Body.Close() + contentType := resp.Header.Get("Content-Type") + if contentType != "text/plain; charset=utf-8" { + t.Errorf("expected content type to be text/plain, got %s", contentType) + } if resp.StatusCode != test.status { t.Errorf("got %d, expected %d from %s", resp.StatusCode, test.status, urlstr) continue diff --git a/core/corehttp/metrics_test.go b/core/corehttp/metrics_test.go index 09bcf6140..5a08b81f9 100644 --- a/core/corehttp/metrics_test.go +++ b/core/corehttp/metrics_test.go @@ -7,9 +7,9 @@ import ( core "github.com/ipfs/go-ipfs/core" - swarmt "gx/ipfs/QmPQoCVRHaGD25VffyB7DFV5qP65hFSQJdSDy75P1vYBKe/go-libp2p-swarm/testing" - bhost "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/host/basic" - inet "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" + bhost "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/host/basic" + inet "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + swarmt "gx/ipfs/Qmb55o5PuhvqwjdVLvc4VV3ouLziYc6TfwM9LC6GwBQokn/go-libp2p-swarm/testing" ) // This test is based on go-libp2p/p2p/net/swarm.TestConnectednessCorrect diff --git a/core/corerepo/gc.go b/core/corerepo/gc.go index 032557a5f..40c5e890c 100644 --- a/core/corerepo/gc.go +++ b/core/corerepo/gc.go @@ -12,8 +12,8 @@ import ( humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" ) var log = logging.Logger("corerepo") diff --git a/core/corerepo/pinning.go b/core/corerepo/pinning.go index 517437879..c943bf3fd 100644 --- a/core/corerepo/pinning.go +++ b/core/corerepo/pinning.go @@ -18,28 +18,21 @@ import ( "fmt" "github.com/ipfs/go-ipfs/core" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" + "github.com/ipfs/go-ipfs/core/coreapi/interface" - cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ) -func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]cid.Cid, error) { +func Pin(n *core.IpfsNode, api iface.CoreAPI, ctx context.Context, paths []string, recursive bool) ([]cid.Cid, error) { out := make([]cid.Cid, len(paths)) - r := &resolver.Resolver{ - DAG: n.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - for i, fpath := range paths { - p, err := path.ParsePath(fpath) + p, err := iface.ParsePath(fpath) if err != nil { return nil, err } - dagnode, err := core.Resolve(ctx, n.Namesys, r, p) + dagnode, err := api.ResolveNode(ctx, p) if err != nil { return nil, fmt.Errorf("pin: %s", err) } @@ -58,30 +51,25 @@ func Pin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) return out, nil } -func Unpin(n *core.IpfsNode, ctx context.Context, paths []string, recursive bool) ([]cid.Cid, error) { +func Unpin(n *core.IpfsNode, api iface.CoreAPI, ctx context.Context, paths []string, recursive bool) ([]cid.Cid, error) { unpinned := make([]cid.Cid, len(paths)) - r := &resolver.Resolver{ - DAG: n.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - for i, p := range paths { - p, err := path.ParsePath(p) + p, err := iface.ParsePath(p) if err != nil { return nil, err } - k, err := core.ResolveToCid(ctx, n.Namesys, r, p) + k, err := api.ResolvePath(ctx, p) if err != nil { return nil, err } - err = n.Pinning.Unpin(ctx, k, recursive) + err = n.Pinning.Unpin(ctx, k.Cid(), recursive) if err != nil { return nil, err } - unpinned[i] = k + unpinned[i] = k.Cid() } err := n.Pinning.Flush() diff --git a/core/coreunix/add.go b/core/coreunix/add.go index ad8450f6a..9e3625a44 100644 --- a/core/coreunix/add.go +++ b/core/coreunix/add.go @@ -11,21 +11,22 @@ import ( "strconv" core "github.com/ipfs/go-ipfs/core" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/pin" - unixfs "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - balanced "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/balanced" - ihelper "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/helpers" - trickle "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer/trickle" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" posinfo "gx/ipfs/QmPG32VXR5jmpo9q8R9FNdR4Ae97Ky9CiZE6SctJLUB79H/go-ipfs-posinfo" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" + unixfs "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + balanced "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/balanced" + ihelper "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/helpers" + trickle "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer/trickle" files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" - chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" + chunker "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) var log = logging.Logger("coreunix") @@ -46,13 +47,6 @@ type Object struct { Size string } -type AddedObject struct { - Name string - Hash string `json:",omitempty"` - Bytes int64 `json:",omitempty"` - Size string `json:",omitempty"` -} - // NewAdder Returns a new Adder used for a file add operation. func NewAdder(ctx context.Context, p pin.Pinner, bs bstore.GCBlockstore, ds ipld.DAGService) (*Adder, error) { return &Adder{ @@ -75,7 +69,7 @@ type Adder struct { pinning pin.Pinner blockstore bstore.GCBlockstore dagService ipld.DAGService - Out chan interface{} + Out chan<- interface{} Progress bool Hidden bool Pin bool @@ -398,8 +392,8 @@ func (adder *Adder) addNode(node ipld.Node, path string) error { return nil } -// AddFile adds the given file while respecting the adder. -func (adder *Adder) AddFile(file files.File) error { +// AddAllAndPin adds the given request's files and pin them. +func (adder *Adder) AddAllAndPin(file files.File) (ipld.Node, error) { if adder.Pin { adder.unlocker = adder.blockstore.PinLock() } @@ -409,7 +403,41 @@ func (adder *Adder) AddFile(file files.File) error { } }() - return adder.addFile(file) + switch { + case file.IsDirectory(): + // Iterate over each top-level file and add individually. Otherwise the + // single files.File f is treated as a directory, affecting hidden file + // semantics. + for { + f, err := file.NextFile() + if err == io.EOF { + // Finished the list of files. + break + } else if err != nil { + return nil, err + } + if err := adder.addFile(f); err != nil { + return nil, err + } + } + break + default: + if err := adder.addFile(file); err != nil { + return nil, err + } + break + } + + // copy intermediary nodes from editor to our actual dagservice + nd, err := adder.Finalize() + if err != nil { + return nil, err + } + + if !adder.Pin { + return nd, nil + } + return nd, adder.PinRoot() } func (adder *Adder) addFile(file files.File) error { @@ -536,7 +564,7 @@ func (adder *Adder) maybePauseForGC() error { } // outputDagnode sends dagnode info over the output channel -func outputDagnode(out chan interface{}, name string, dn ipld.Node) error { +func outputDagnode(out chan<- interface{}, name string, dn ipld.Node) error { if out == nil { return nil } @@ -546,7 +574,7 @@ func outputDagnode(out chan interface{}, name string, dn ipld.Node) error { return err } - out <- &AddedObject{ + out <- &coreiface.AddEvent{ Hash: o.Hash, Name: name, Size: o.Size, @@ -581,7 +609,7 @@ func getOutput(dagnode ipld.Node) (*Object, error) { type progressReader struct { file files.File - out chan interface{} + out chan<- interface{} bytes int64 lastProgress int64 } @@ -592,7 +620,7 @@ func (i *progressReader) Read(p []byte) (int, error) { i.bytes += int64(n) if i.bytes-i.lastProgress >= progressReaderIncrement || err == io.EOF { i.lastProgress = i.bytes - i.out <- &AddedObject{ + i.out <- &coreiface.AddEvent{ Name: i.file.FileName(), Bytes: i.bytes, } diff --git a/core/coreunix/add_test.go b/core/coreunix/add_test.go index d2c9c7337..f37b42dad 100644 --- a/core/coreunix/add_test.go +++ b/core/coreunix/add_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ipfs/go-ipfs/core" + coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "github.com/ipfs/go-ipfs/pin/gc" "github.com/ipfs/go-ipfs/repo" @@ -18,12 +19,12 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" files "gx/ipfs/QmSP88ryZkHSRn1fnngAaV2Vcn63WUJzAavnRM9CVdU1Ky/go-ipfs-cmdkit/files" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe" @@ -85,7 +86,7 @@ func TestAddGCLive(t *testing.T) { go func() { defer close(addDone) defer close(out) - err := adder.AddFile(slf) + _, err := adder.AddAllAndPin(slf) if err != nil { t.Fatal(err) @@ -96,7 +97,7 @@ func TestAddGCLive(t *testing.T) { addedHashes := make(map[string]struct{}) select { case o := <-out: - addedHashes[o.(*AddedObject).Hash] = struct{}{} + addedHashes[o.(*coreiface.AddEvent).Hash] = struct{}{} case <-addDone: t.Fatal("add shouldnt complete yet") } @@ -124,7 +125,7 @@ func TestAddGCLive(t *testing.T) { // receive next object from adder o := <-out - addedHashes[o.(*AddedObject).Hash] = struct{}{} + addedHashes[o.(*coreiface.AddEvent).Hash] = struct{}{} <-gcstarted @@ -140,7 +141,7 @@ func TestAddGCLive(t *testing.T) { var last cid.Cid for a := range out { // wait for it to finish - c, err := cid.Decode(a.(*AddedObject).Hash) + c, err := cid.Decode(a.(*coreiface.AddEvent).Hash) if err != nil { t.Fatal(err) } @@ -178,7 +179,8 @@ func testAddWPosInfo(t *testing.T, rawLeaves bool) { if err != nil { t.Fatal(err) } - adder.Out = make(chan interface{}) + out := make(chan interface{}) + adder.Out = out adder.Progress = true adder.RawLeaves = rawLeaves adder.NoCopy = true @@ -191,12 +193,12 @@ func testAddWPosInfo(t *testing.T, rawLeaves bool) { go func() { defer close(adder.Out) - err = adder.AddFile(file) + _, err = adder.AddAllAndPin(file) if err != nil { t.Fatal(err) } }() - for range adder.Out { + for range out { } exp := 0 diff --git a/core/coreunix/cat.go b/core/coreunix/cat.go deleted file mode 100644 index 76635751e..000000000 --- a/core/coreunix/cat.go +++ /dev/null @@ -1,24 +0,0 @@ -package coreunix - -import ( - "context" - - core "github.com/ipfs/go-ipfs/core" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" -) - -func Cat(ctx context.Context, n *core.IpfsNode, pstr string) (uio.DagReader, error) { - r := &resolver.Resolver{ - DAG: n.DAG, - ResolveOnce: uio.ResolveUnixfsOnce, - } - - dagNode, err := core.Resolve(ctx, n.Namesys, r, path.Path(pstr)) - if err != nil { - return nil, err - } - - return uio.NewDagReader(ctx, dagNode, n.DAG) -} diff --git a/core/coreunix/metadata.go b/core/coreunix/metadata.go index b38ccabe1..0ebd922a3 100644 --- a/core/coreunix/metadata.go +++ b/core/coreunix/metadata.go @@ -3,8 +3,8 @@ package coreunix import ( core "github.com/ipfs/go-ipfs/core" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ) func AddMetadataTo(n *core.IpfsNode, skey string, m *ft.Metadata) (string, error) { diff --git a/core/coreunix/metadata_test.go b/core/coreunix/metadata_test.go index e66eda5b6..54fa7dc5a 100644 --- a/core/coreunix/metadata_test.go +++ b/core/coreunix/metadata_test.go @@ -7,20 +7,20 @@ import ( "testing" core "github.com/ipfs/go-ipfs/core" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - importer "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + importer "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" + chunker "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) func getDagserv(t *testing.T) ipld.DAGService { diff --git a/core/mock/mock.go b/core/mock/mock.go index 0dd17ec9e..c0010210b 100644 --- a/core/mock/mock.go +++ b/core/mock/mock.go @@ -8,14 +8,14 @@ import ( "github.com/ipfs/go-ipfs/repo" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - libp2p "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" + host "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + libp2p "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - host "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) // NewMockNode constructs an IpfsNode for use in tests. diff --git a/core/pathresolver.go b/core/pathresolver.go index db8a0dcae..ff96d634c 100644 --- a/core/pathresolver.go +++ b/core/pathresolver.go @@ -6,10 +6,9 @@ import ( "strings" namesys "github.com/ipfs/go-ipfs/namesys" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - resolver "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path/resolver" - cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + resolver "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path/resolver" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -74,37 +73,3 @@ func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, // ok, we have an IPFS path now (or what we'll treat as one) return r.ResolvePath(ctx, p) } - -// ResolveToCid resolves a path to a cid. -// -// It first checks if the path is already in the form of just a cid ( or -// /ipfs/) and returns immediately if so. Otherwise, it falls back onto -// Resolve to perform resolution of the dagnode being referenced. -func ResolveToCid(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (cid.Cid, error) { - - // If the path is simply a cid, parse and return it. Parsed paths are already - // normalized (read: prepended with /ipfs/ if needed), so segment[1] should - // always be the key. - if p.IsJustAKey() { - return cid.Decode(p.Segments()[1]) - } - - // Fall back onto regular dagnode resolution. Retrieve the second-to-last - // segment of the path and resolve its link to the last segment. - head, tail, err := p.PopLastSegment() - if err != nil { - return cid.Cid{}, err - } - dagnode, err := Resolve(ctx, nsys, r, head) - if err != nil { - return cid.Cid{}, err - } - - // Extract and return the cid of the link to the target dag node. - link, _, err := dagnode.ResolveLink([]string{tail}) - if err != nil { - return cid.Cid{}, err - } - - return link.Cid, nil -} diff --git a/core/pathresolver_test.go b/core/pathresolver_test.go index 8ff6c84db..9df974068 100644 --- a/core/pathresolver_test.go +++ b/core/pathresolver_test.go @@ -5,7 +5,7 @@ import ( core "github.com/ipfs/go-ipfs/core" coremock "github.com/ipfs/go-ipfs/core/mock" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ) func TestResolveNoComponents(t *testing.T) { diff --git a/dagutils/diff.go b/dagutils/diff.go index 13287c4c2..830e5fff5 100644 --- a/dagutils/diff.go +++ b/dagutils/diff.go @@ -8,7 +8,7 @@ import ( coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface" "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -94,26 +94,24 @@ func ApplyChange(ctx context.Context, ds ipld.DAGService, nd *dag.ProtoNode, cs return e.Finalize(ctx, ds) } -// Diff returns a set of changes that transform node 'a' into node 'b' +// Diff returns a set of changes that transform node 'a' into node 'b'. +// It only traverses links in the following cases: +// 1. two node's links number are greater than 0. +// 2. both of two nodes are ProtoNode. +// Otherwise, it compares the cid and emits a Mod change object. func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, error) { // Base case where both nodes are leaves, just compare // their CIDs. if len(a.Links()) == 0 && len(b.Links()) == 0 { - if a.Cid().Equals(b.Cid()) { - return []*Change{}, nil - } - return []*Change{ - &Change{ - Type: Mod, - Before: a.Cid(), - After: b.Cid(), - }, - }, nil + return getChange(a, b) } var out []*Change - cleanA := a.Copy().(*dag.ProtoNode) - cleanB := b.Copy().(*dag.ProtoNode) + cleanA, okA := a.Copy().(*dag.ProtoNode) + cleanB, okB := b.Copy().(*dag.ProtoNode) + if !okA || !okB { + return getChange(a, b) + } // strip out unchanged stuff for _, lnk := range a.Links() { @@ -132,17 +130,7 @@ func Diff(ctx context.Context, ds ipld.DAGService, a, b ipld.Node) ([]*Change, e return nil, err } - anodepb, ok := anode.(*dag.ProtoNode) - if !ok { - return nil, dag.ErrNotProtobuf - } - - bnodepb, ok := bnode.(*dag.ProtoNode) - if !ok { - return nil, dag.ErrNotProtobuf - } - - sub, err := Diff(ctx, ds, anodepb, bnodepb) + sub, err := Diff(ctx, ds, anode, bnode) if err != nil { return nil, err } @@ -209,3 +197,16 @@ func MergeDiffs(a, b []*Change) ([]*Change, []Conflict) { } return out, conflicts } + +func getChange(a, b ipld.Node) ([]*Change, error) { + if a.Cid().Equals(b.Cid()) { + return []*Change{}, nil + } + return []*Change{ + { + Type: Mod, + Before: a.Cid(), + After: b.Cid(), + }, + }, nil +} diff --git a/dagutils/diffenum.go b/dagutils/diffenum.go index ee1a6ab04..b62a9c5f1 100644 --- a/dagutils/diffenum.go +++ b/dagutils/diffenum.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - mdag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + mdag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" diff --git a/dagutils/diffenum_test.go b/dagutils/diffenum_test.go index 23f1c438f..d02bf526a 100644 --- a/dagutils/diffenum_test.go +++ b/dagutils/diffenum_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - mdtest "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag/test" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + mdtest "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag/test" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" diff --git a/dagutils/utils.go b/dagutils/utils.go index 32c57fa1c..e9cd33248 100644 --- a/dagutils/utils.go +++ b/dagutils/utils.go @@ -4,15 +4,15 @@ import ( "context" "errors" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - syncds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + syncds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) // Editor represents a ProtoNode tree editor and provides methods to diff --git a/dagutils/utils_test.go b/dagutils/utils_test.go index bd951511b..7fb6c7806 100644 --- a/dagutils/utils_test.go +++ b/dagutils/utils_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - mdtest "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag/test" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + mdtest "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag/test" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" diff --git a/docs/debug-guide.md b/docs/debug-guide.md index b7f5e0b42..9ef046a47 100644 --- a/docs/debug-guide.md +++ b/docs/debug-guide.md @@ -4,8 +4,9 @@ This is a document for helping debug go-ipfs. Please add to it if you can! ### Table of Contents - [Beginning](#beginning) -- [Analysing the stack dump](#analysing-the-stack-dump) +- [Analyzing the stack dump](#analyzing-the-stack-dump) - [Analyzing the CPU Profile](#analyzing-the-cpu-profile) +- [Analyzing vars and memory statistics](#analyzing-vars-and-memory-statistics) - [Other](#other) ### Beginning @@ -20,6 +21,8 @@ profiling information. - `curl localhost:5001/debug/pprof/profile > ipfs.cpuprof` - heap trace dump - `curl localhost:5001/debug/pprof/heap > ipfs.heap` +- memory statistics (in json, see "memstats" object) + - `curl localhost:5001/debug/vars > ipfs.vars` - system information - `ipfs diag sys > ipfs.sysinfo` @@ -28,7 +31,7 @@ Bundle all that up and include a copy of the ipfs binary that you are running You can investigate yourself if you feel intrepid: -### Analysing the stack dump +### Analyzing the stack dump The first thing to look for is hung goroutines -- any goroutine thats been stuck for over a minute will note that in the trace. It looks something like: @@ -84,6 +87,10 @@ about `go tool pprof`. My go-to method of analyzing these is to run the `web` command, which generates an SVG dotgraph and opens it in your browser. This is the quickest way to easily point out where the hot spots in the code are. +### Analyzing vars and memory statistics + +The output is JSON formatted and includes badger store statistics, the command line run, and the output from Go's [runtime.ReadMemStats](https://golang.org/pkg/runtime/#ReadMemStats). The [MemStats](https://golang.org/pkg/runtime/#MemStats) has useful information about memory allocation and garbage collection. + ### Other If you have any questions, or want us to analyze some weird go-ipfs behaviour, diff --git a/docs/experimental-features.md b/docs/experimental-features.md index 596b8e7f3..0acd5820f 100644 --- a/docs/experimental-features.md +++ b/docs/experimental-features.md @@ -183,7 +183,7 @@ Allows ipfs to retrieve blocks contents via a url instead of storing it in the d experimental. ### In Version -???. +master, v0.4.17 ### How to enable Modify your ipfs config: @@ -191,8 +191,14 @@ Modify your ipfs config: ipfs config --json Experimental.UrlstoreEnabled true ``` +And then add a file at a specific URL using `ipfs urlstore add ` + ### Road to being a real feature -???. +- [ ] Needs more people to use and report on how well it works. +- [ ] Need to address error states and failure conditions +- [ ] Need to write docs on usage, advantages, disadvantages +- [ ] Need to implement caching +- [ ] Need to add metrics to monitor performance --- diff --git a/exchange/reprovide/providers.go b/exchange/reprovide/providers.go index c579d0357..c8b12213d 100644 --- a/exchange/reprovide/providers.go +++ b/exchange/reprovide/providers.go @@ -7,9 +7,9 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" cidutil "gx/ipfs/QmQJSeE3CX4zos9qeaG8EhecEK9zvrTEfTG84J8C5NVRwt/go-cidutil" - merkledag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + merkledag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + blocks "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - blocks "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) // NewBlockstoreProvider returns key provider using bstore.AllKeysChan diff --git a/exchange/reprovide/reprovide.go b/exchange/reprovide/reprovide.go index 27628b35a..f21633905 100644 --- a/exchange/reprovide/reprovide.go +++ b/exchange/reprovide/reprovide.go @@ -7,7 +7,7 @@ import ( backoff "gx/ipfs/QmPJUtEJsm5YLUWhF6imvyCH8KZXRJa9Wup7FDMwTy5Ufz/backoff" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" "gx/ipfs/QmVkMRSkXrpjqrroEXWuYBvDBnXCdMMY6gsKicBGVGUqKT/go-verifcid" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" ) diff --git a/exchange/reprovide/reprovide_test.go b/exchange/reprovide/reprovide_test.go index c53a49023..f3615b85d 100644 --- a/exchange/reprovide/reprovide_test.go +++ b/exchange/reprovide/reprovide_test.go @@ -5,12 +5,12 @@ import ( "testing" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" + mock "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/mock" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" - mock "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/mock" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" . "github.com/ipfs/go-ipfs/exchange/reprovide" ) diff --git a/filestore/filestore.go b/filestore/filestore.go index b7dad3c55..1ad7471fb 100644 --- a/filestore/filestore.go +++ b/filestore/filestore.go @@ -14,9 +14,9 @@ import ( posinfo "gx/ipfs/QmPG32VXR5jmpo9q8R9FNdR4Ae97Ky9CiZE6SctJLUB79H/go-ipfs-posinfo" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" - dsq "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + dsq "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/query" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) var log = logging.Logger("filestore") diff --git a/filestore/filestore_test.go b/filestore/filestore_test.go index 42681c64a..98861cf3f 100644 --- a/filestore/filestore_test.go +++ b/filestore/filestore_test.go @@ -7,12 +7,12 @@ import ( "math/rand" "testing" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" posinfo "gx/ipfs/QmPG32VXR5jmpo9q8R9FNdR4Ae97Ky9CiZE6SctJLUB79H/go-ipfs-posinfo" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) func newTestFilestore(t *testing.T) (string, *Filestore) { diff --git a/filestore/fsrefstore.go b/filestore/fsrefstore.go index 5e8bf6396..7ecfaae8c 100644 --- a/filestore/fsrefstore.go +++ b/filestore/fsrefstore.go @@ -13,11 +13,11 @@ import ( posinfo "gx/ipfs/QmPG32VXR5jmpo9q8R9FNdR4Ae97Ky9CiZE6SctJLUB79H/go-ipfs-posinfo" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" - dshelp "gx/ipfs/QmUDTSi6zJ6ACyQaKtxscCUxrg5DaXs9r4RQUPFQXGPHpo/go-ipfs-ds-help" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dsns "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/namespace" - dsq "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + dshelp "gx/ipfs/QmS73grfbWgWrNztd8Lns9GCG3jjRNDfcPYg2VYQzKDZSt/go-ipfs-ds-help" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dsns "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/namespace" + dsq "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/query" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" proto "gx/ipfs/QmdxUuburamoF6zF9qjeQC4WYcWGbWuRmdLacMEsW8ioD8/gogo-protobuf/proto" ) diff --git a/filestore/util.go b/filestore/util.go index 6213b0f10..39df78c6f 100644 --- a/filestore/util.go +++ b/filestore/util.go @@ -7,10 +7,10 @@ import ( pb "github.com/ipfs/go-ipfs/filestore/pb" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - dshelp "gx/ipfs/QmUDTSi6zJ6ACyQaKtxscCUxrg5DaXs9r4RQUPFQXGPHpo/go-ipfs-ds-help" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dsq "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + dshelp "gx/ipfs/QmS73grfbWgWrNztd8Lns9GCG3jjRNDfcPYg2VYQzKDZSt/go-ipfs-ds-help" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dsq "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/query" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) // Status is used to identify the state of the block data referenced diff --git a/fuse/ipns/common.go b/fuse/ipns/common.go index 0b1e09a90..2da8014cc 100644 --- a/fuse/ipns/common.go +++ b/fuse/ipns/common.go @@ -6,8 +6,8 @@ import ( "github.com/ipfs/go-ipfs/core" nsys "github.com/ipfs/go-ipfs/namesys" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ) // InitializeKeyspace sets the ipns record for the given key to diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index 1e2e596e4..f9b967bf4 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -17,8 +17,8 @@ import ( ci "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil/ci" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" + offroute "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" fstest "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse/fs/fstestutil" - offroute "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" racedet "gx/ipfs/Qmf7HqcW7LtCi1W8y2bdx2eJpze74jkbKqpByxgXikdbLF/go-detect-race" ) diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index 61d94c593..31ea71f5a 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -13,16 +13,16 @@ import ( core "github.com/ipfs/go-ipfs/core" namesys "github.com/ipfs/go-ipfs/namesys" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" + mfs "gx/ipfs/QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ/go-mfs" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" fuse "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse" fs "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse/fs" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - mfs "gx/ipfs/QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2/go-mfs" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ) diff --git a/fuse/node/mount_test.go b/fuse/node/mount_test.go index 8bab1e2ef..cd4fc592c 100644 --- a/fuse/node/mount_test.go +++ b/fuse/node/mount_test.go @@ -16,7 +16,7 @@ import ( namesys "github.com/ipfs/go-ipfs/namesys" ci "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil/ci" - offroute "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" + offroute "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" ) func maybeSkipFuseTests(t *testing.T) { diff --git a/fuse/readonly/ipfs_test.go b/fuse/readonly/ipfs_test.go index e17892d0a..d300068cb 100644 --- a/fuse/readonly/ipfs_test.go +++ b/fuse/readonly/ipfs_test.go @@ -14,16 +14,17 @@ import ( "testing" core "github.com/ipfs/go-ipfs/core" - coreunix "github.com/ipfs/go-ipfs/core/coreunix" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" + iface "github.com/ipfs/go-ipfs/core/coreapi/interface" coremock "github.com/ipfs/go-ipfs/core/mock" - importer "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" ci "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil/ci" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" + importer "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" fstest "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse/fs/fstestutil" - chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + chunker "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -116,6 +117,8 @@ func TestIpfsStressRead(t *testing.T) { nd, mnt := setupIpfsTest(t, nil) defer mnt.Close() + api := coreapi.NewCoreAPI(nd) + var nodes []ipld.Node var paths []string @@ -165,14 +168,14 @@ func TestIpfsStressRead(t *testing.T) { defer wg.Done() for i := 0; i < 2000; i++ { - item := paths[rand.Intn(len(paths))] - fname := path.Join(mnt.Dir, item) + item, _ := iface.ParsePath(paths[rand.Intn(len(paths))]) + fname := path.Join(mnt.Dir, item.String()) rbuf, err := ioutil.ReadFile(fname) if err != nil { errs <- err } - read, err := coreunix.Cat(nd.Context(), nd, item) + read, err := api.Unixfs().Cat(nd.Context(), item) if err != nil { errs <- err } diff --git a/fuse/readonly/readonly_unix.go b/fuse/readonly/readonly_unix.go index d52a71fc9..2f12c5693 100644 --- a/fuse/readonly/readonly_unix.go +++ b/fuse/readonly/readonly_unix.go @@ -11,10 +11,10 @@ import ( "syscall" core "github.com/ipfs/go-ipfs/core" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - mdag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + mdag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" lgbl "gx/ipfs/QmNLzS18jsmwTxXewTm3YnZVLftWCeegNZEBFjMrnvnBrH/go-libp2p-loggables" fuse "gx/ipfs/QmSJBsmLP1XMjv8hxYg2rUMdPDB7YUpyBo9idjrJ6Cmq6F/fuse" diff --git a/namesys/base.go b/namesys/base.go index c24832799..e090236bc 100644 --- a/namesys/base.go +++ b/namesys/base.go @@ -7,7 +7,7 @@ import ( context "context" opts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ) type onceResult struct { diff --git a/namesys/cache.go b/namesys/cache.go index f18c6e8aa..8272c2bdb 100644 --- a/namesys/cache.go +++ b/namesys/cache.go @@ -3,7 +3,7 @@ package namesys import ( "time" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ) func (ns *mpns) cacheGet(name string) (path.Path, bool) { diff --git a/namesys/dns.go b/namesys/dns.go index f90880de9..8dee79ba9 100644 --- a/namesys/dns.go +++ b/namesys/dns.go @@ -7,8 +7,8 @@ import ( "strings" opts "github.com/ipfs/go-ipfs/namesys/opts" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" isd "gx/ipfs/QmZmmuAXgX73UQmX1jRKjTGmjzq24Jinqkq8vzkBtno4uX/go-is-domain" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) type LookupTXTFunc func(name string) (txt []string, err error) diff --git a/namesys/interface.go b/namesys/interface.go index dd195cc9a..dcbce47b7 100644 --- a/namesys/interface.go +++ b/namesys/interface.go @@ -36,7 +36,7 @@ import ( context "context" opts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" ) diff --git a/namesys/ipns_resolver_validation_test.go b/namesys/ipns_resolver_validation_test.go index 36e5fdc67..48ac935b8 100644 --- a/namesys/ipns_resolver_validation_test.go +++ b/namesys/ipns_resolver_validation_test.go @@ -6,22 +6,22 @@ import ( "time" opts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" + mockrouting "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/mock" + offline "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" record "gx/ipfs/QmSb4B8ZAAj5ALe9LjfzPyF8Ma6ezC1NTnDF2JQPUJxEXb/go-libp2p-record" - mockrouting "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/mock" - offline "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" - ropts "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing/options" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + ropts "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing/options" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" + pstoremem "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore/pstoremem" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" - pstoremem "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore/pstoremem" ) func TestResolverValidation(t *testing.T) { diff --git a/namesys/namesys.go b/namesys/namesys.go index 1099997b2..865852617 100644 --- a/namesys/namesys.go +++ b/namesys/namesys.go @@ -6,14 +6,14 @@ import ( "time" opts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" lru "gx/ipfs/QmQjMHF8ptRgx4E57UFMiT4YM6kqaJeYxZ1MCDX23aw4rK/golang-lru" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" isd "gx/ipfs/QmZmmuAXgX73UQmX1jRKjTGmjzq24Jinqkq8vzkBtno4uX/go-is-domain" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ) diff --git a/namesys/namesys_test.go b/namesys/namesys_test.go index 301c98a5f..915b89fa6 100644 --- a/namesys/namesys_test.go +++ b/namesys/namesys_test.go @@ -8,14 +8,14 @@ import ( opts "github.com/ipfs/go-ipfs/namesys/opts" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - offroute "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/offline" - "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + offroute "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/offline" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + pstoremem "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore/pstoremem" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" - pstoremem "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore/pstoremem" ) type mockResolver struct { diff --git a/namesys/proquint.go b/namesys/proquint.go index ad09fd48c..36e845bbe 100644 --- a/namesys/proquint.go +++ b/namesys/proquint.go @@ -5,8 +5,8 @@ import ( "errors" opts "github.com/ipfs/go-ipfs/namesys/opts" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" proquint "gx/ipfs/QmYnf27kzqR2cxt6LFZdrAFJuQd6785fTkBvMuEj9EeRxM/proquint" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" ) type ProquintResolver struct{} diff --git a/namesys/publisher.go b/namesys/publisher.go index b85420675..a5e2eae7e 100644 --- a/namesys/publisher.go +++ b/namesys/publisher.go @@ -7,15 +7,15 @@ import ( "time" pin "github.com/ipfs/go-ipfs/pin" - ft "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + ft "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dsquery "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" - pb "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns/pb" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + pb "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns/pb" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dsquery "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/query" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" proto "gx/ipfs/QmdxUuburamoF6zF9qjeQC4WYcWGbWuRmdLacMEsW8ioD8/gogo-protobuf/proto" base32 "gx/ipfs/QmfVj3x4D6Jkq9SEoi5n2NmoUomLwoeiwnYz2KQa15wRw6/base32" diff --git a/namesys/publisher_test.go b/namesys/publisher_test.go index 3f6e6f02e..b55742e14 100644 --- a/namesys/publisher_test.go +++ b/namesys/publisher_test.go @@ -8,12 +8,12 @@ import ( testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" ci "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" - mockrouting "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/mock" - dshelp "gx/ipfs/QmUDTSi6zJ6ACyQaKtxscCUxrg5DaXs9r4RQUPFQXGPHpo/go-ipfs-ds-help" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" + mockrouting "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/mock" + dshelp "gx/ipfs/QmS73grfbWgWrNztd8Lns9GCG3jjRNDfcPYg2VYQzKDZSt/go-ipfs-ds-help" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ) diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index ebe17c776..e2e650c46 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -7,14 +7,14 @@ import ( keystore "github.com/ipfs/go-ipfs/keystore" namesys "github.com/ipfs/go-ipfs/namesys" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" ic "gx/ipfs/QmPvyPwuCgJ7pDmrKDxRtsScJgBaM5h4EpRL2qQJsmXf4n/go-libp2p-crypto" goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" gpctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" + pb "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns/pb" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - pb "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns/pb" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" proto "gx/ipfs/QmdxUuburamoF6zF9qjeQC4WYcWGbWuRmdLacMEsW8ioD8/gogo-protobuf/proto" ) diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go index dd8693965..0a3afbf0b 100644 --- a/namesys/republisher/repub_test.go +++ b/namesys/republisher/repub_test.go @@ -10,11 +10,11 @@ import ( mock "github.com/ipfs/go-ipfs/core/mock" namesys "github.com/ipfs/go-ipfs/namesys" . "github.com/ipfs/go-ipfs/namesys/republisher" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ) func TestRepublish(t *testing.T) { diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go index 82e3f06da..18abb6897 100644 --- a/namesys/resolve_test.go +++ b/namesys/resolve_test.go @@ -6,13 +6,13 @@ import ( "testing" "time" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - mockrouting "gx/ipfs/QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ/go-ipfs-routing/mock" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" + mockrouting "gx/ipfs/QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW/go-ipfs-routing/mock" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" ) diff --git a/namesys/routing.go b/namesys/routing.go index 6ac9f081a..f5dfa462e 100644 --- a/namesys/routing.go +++ b/namesys/routing.go @@ -6,15 +6,15 @@ import ( "time" opts "github.com/ipfs/go-ipfs/namesys/opts" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" - routing "gx/ipfs/QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG/go-libp2p-routing" + dht "gx/ipfs/QmTdMq4uYZXmGW3u6KgnpCRWjo1Y7dWjRuAaGPw7Qxqr1s/go-libp2p-kad-dht" + routing "gx/ipfs/QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU/go-libp2p-routing" + ipns "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns" + pb "gx/ipfs/QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o/go-ipns/pb" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - dht "gx/ipfs/QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME/go-libp2p-kad-dht" - ipns "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns" - pb "gx/ipfs/QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb/go-ipns/pb" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" proto "gx/ipfs/QmdxUuburamoF6zF9qjeQC4WYcWGbWuRmdLacMEsW8ioD8/gogo-protobuf/proto" ) diff --git a/p2p/listener.go b/p2p/listener.go index c0dce1bd4..f03130a89 100644 --- a/p2p/listener.go +++ b/p2p/listener.go @@ -4,10 +4,10 @@ import ( "errors" "sync" + p2phost "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" + net "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" - p2phost "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" - net "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" ) // Listener listens for connections and proxies them to a target diff --git a/p2p/local.go b/p2p/local.go index 381156691..6773527e8 100644 --- a/p2p/local.go +++ b/p2p/local.go @@ -6,10 +6,10 @@ import ( "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net" tec "gx/ipfs/QmWHgLqrghM9zw77nF6gdvT9ExQ2RB9pLxkd8sDHZf1rWb/go-temp-err-catcher" + "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" ) // localListener manet streams and proxies them to libp2p services diff --git a/p2p/p2p.go b/p2p/p2p.go index 237c891e0..8dc3c29fb 100644 --- a/p2p/p2p.go +++ b/p2p/p2p.go @@ -1,10 +1,10 @@ package p2p import ( + p2phost "gx/ipfs/QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2/go-libp2p-host" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - p2phost "gx/ipfs/QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2/go-libp2p-host" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) var log = logging.Logger("p2p-mount") diff --git a/p2p/remote.go b/p2p/remote.go index 13ae4d8ed..3a3f0937e 100644 --- a/p2p/remote.go +++ b/p2p/remote.go @@ -4,9 +4,9 @@ import ( "context" manet "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net" + net "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" - net "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" ) var maPrefix = "/" + ma.ProtocolWithCode(ma.P_IPFS).Name + "/" diff --git a/p2p/stream.go b/p2p/stream.go index 6d49614e9..f322cf1aa 100644 --- a/p2p/stream.go +++ b/p2p/stream.go @@ -5,11 +5,11 @@ import ( "sync" manet "gx/ipfs/QmV6FjemM1K8oXjrvuq3wuVWWoU2TLDPmNnKrxHzY3v6Ai/go-multiaddr-net" - ifconnmgr "gx/ipfs/QmV9T3rTezwJhMJQBzVrGj2tncJwv23dTKdxzXrUxAvWFi/go-libp2p-interface-connmgr" + net "gx/ipfs/QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa/go-libp2p-net" + ifconnmgr "gx/ipfs/QmXPqoktJEKkWPT6rSdhCM2G3E1yR7uUBdjnJrhJYeBgHU/go-libp2p-interface-connmgr" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer" - net "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net" ) const cmgrTag = "stream-fwd" diff --git a/package.json b/package.json index cafdcd7ea..c1979994f 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,9 @@ }, { "author": "whyrusleeping", - "hash": "QmPJ6U14u5D2abGVkF3dopCeM1JqigVTUJ7jbAHjTnGZrt", + "hash": "QmZSHe9kqEcqUG6DSBrKYULk8EeZLDd1skpHNoSaK6rW4M", "name": "go-libp2p-secio", - "version": "2.0.10" + "version": "2.0.14" }, { "author": "whyrusleeping", @@ -47,9 +47,9 @@ "version": "0.1.3" }, { - "hash": "QmQkqNJobSLRcrjWT1L8vWFvEpndtoCG5iMRcd9DKdDMKR", + "hash": "QmZ7Kqf9pbNvopSpC6L1UbV3ZbphShuv4554QdYGjKY2rM", "name": "iptb", - "version": "1.3.13" + "version": "99.3.9" }, { "hash": "QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8", @@ -94,9 +94,9 @@ }, { "author": "jbenet", - "hash": "QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV", + "hash": "QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D", "name": "go-datastore", - "version": "3.2.0" + "version": "3.4.0" }, { "author": "hashicorp", @@ -106,9 +106,9 @@ }, { "author": "whyrusleeping", - "hash": "QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st", + "hash": "QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX", "name": "go-libp2p-peerstore", - "version": "2.0.1" + "version": "2.0.3" }, { "author": "whyrusleeping", @@ -124,9 +124,9 @@ }, { "author": "whyrusleeping", - "hash": "QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW", + "hash": "QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8", "name": "go-libp2p", - "version": "6.0.13" + "version": "6.0.17" }, { "author": "whyrusleeping", @@ -136,21 +136,21 @@ }, { "author": "whyrusleeping", - "hash": "QmY8toEWLh1zpSCeQTP8kZDRm1dik3cck9p2miCK1QgaAi", + "hash": "QmbYQHTSz4Sg4Y2Vyd7hftGgM1yXwSUBKb47VpoPRuP5Nc", "name": "go-ds-flatfs", - "version": "1.3.2" + "version": "1.3.3" }, { "author": "whyrusleeping", - "hash": "QmYY98HGLuMUm7cLM8Afmvzzw6G5Md6s7pVW78Hd7hJAiA", + "hash": "QmQS6UXi1R87y9nEgnCNmG6YfMzvBSLir7xUheMNFP3hoe", "name": "go-ds-measure", - "version": "1.4.2" + "version": "1.4.3" }, { "author": "whyrusleeping", - "hash": "QmPnXsHj9W8WpDDwj2iogRcnVL6d5ANtK9SAJLgKpeBMq8", + "hash": "QmccqjKZUTqp4ikWNyAbjBuP5HEdqSqRuAr9mcEhYab54a", "name": "go-ds-leveldb", - "version": "1.1.2" + "version": "1.2.1" }, { "author": "whyrusleeping", @@ -171,9 +171,9 @@ "version": "0.2.0" }, { - "hash": "QmZVakpN44VAUxs9eXAuUGLFYTCGmSyqSy6hyEKfMv68ME", + "hash": "QmTdMq4uYZXmGW3u6KgnpCRWjo1Y7dWjRuAaGPw7Qxqr1s", "name": "go-libp2p-kad-dht", - "version": "4.4.2" + "version": "4.4.6" }, { "author": "whyrusleeping", @@ -183,9 +183,9 @@ }, { "author": "whyrusleeping", - "hash": "QmPbYVFhKxamZAN9MyrQMDeoGYa6zkQkhAPguwFfzxPM1J", + "hash": "Qmbi2MdNz6bdqWJg9Fud3WCqTdzP4DXKBwYD16EJVkjzKX", "name": "go-libp2p-floodsub", - "version": "0.9.29" + "version": "0.9.33" }, { "author": "whyrusleeping", @@ -212,9 +212,9 @@ }, { "author": "whyrusleeping", - "hash": "QmYsbnP57nNUKWijs8o2q3ZFrSUcAGTdKoQPuSJC3Uxt1Y", + "hash": "QmQvMxiavoMJzuLPuqrzVX4nXZpMks29hqpv13d81aJNEF", "name": "go-smux-multiplex", - "version": "3.0.13" + "version": "3.0.15" }, { "author": "blang", @@ -224,9 +224,9 @@ }, { "author": "libp2p", - "hash": "QmZaQ3K9PRd5sYYoG1xbTGPtd3N7TYiKBRmcBUTsx8HVET", + "hash": "QmNmyLmysLFuSRjNTW8XrbovrNYFbZoMknTcpYR2AvvDc3", "name": "go-libp2p-pnet", - "version": "3.0.2" + "version": "3.0.3" }, { "author": "kubuxu", @@ -235,15 +235,15 @@ "version": "0.2.3" }, { - "hash": "QmRtUtF42geEhpRg9z45ZfBqRMC6xyeNW7i1iqha3nRMFe", + "hash": "Qmb4AZNKg9yQVKkQqejEcg86AaT6EqGemGV8mBjkfJBeGf", "name": "go-libp2p-kbucket", - "version": "2.2.8" + "version": "2.2.10" }, { "author": "whyrusleeping", - "hash": "QmcsgrV3nCAKjiHKZhKVXWc4oY3WBECJCqahXEMpHeMrev", + "hash": "QmejxafYByb7s4rEMoKjmThZm6HfQ1seASNejVNKde6LBZ", "name": "go-smux-yamux", - "version": "2.0.3" + "version": "2.0.4" }, { "author": "whyrusleeping", @@ -277,9 +277,9 @@ }, { "author": "whyrusleeping", - "hash": "QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq", + "hash": "QmWUPYHpNv4YahaBYXovuEJttgfqcNcN9Gg4arhQYcRoqa", "name": "go-libp2p-net", - "version": "3.0.10" + "version": "3.0.12" }, { "author": "whyrusleeping", @@ -289,15 +289,15 @@ }, { "author": "whyrusleeping", - "hash": "QmeA5hsqgLryvkeyqeQdvGDqurLkYi3XEPLZP3pzuBJXh2", + "hash": "QmQKod7iLxQK6X3aFYvhDDnFdXo3QjxKeL2F7UrPtdKQR2", "name": "go-libp2p-host", - "version": "3.0.10" + "version": "3.0.12" }, { "author": "whyrusleeping", - "hash": "QmPQoCVRHaGD25VffyB7DFV5qP65hFSQJdSDy75P1vYBKe", + "hash": "Qmb55o5PuhvqwjdVLvc4VV3ouLziYc6TfwM9LC6GwBQokn", "name": "go-libp2p-swarm", - "version": "3.0.12" + "version": "3.0.17" }, { "hash": "QmXTmUCBtDUrzDYVzASogLiNph7EBuYqEgPL7QoHNMzUnz", @@ -333,9 +333,9 @@ "version": "0.2.0" }, { - "hash": "QmVBnJDKhtFXTRVjXKinqpwGu8t1DyNqPKan2iGX8PR8xG", + "hash": "QmVQPj6rHdqz6dDQrjcdP36zDYLaoB7xwqRg39kx2PqqKU", "name": "go-libp2p-routing", - "version": "2.6.2" + "version": "2.6.4" }, { "author": "whyrusleeping", @@ -350,15 +350,15 @@ }, { "author": "vyzo", - "hash": "QmS5X31wA86RSjQqCUHG2CLPoFNnBZ3UMy1ikfBHQ3G6LG", + "hash": "Qmf5M8FECT1H1NGZ9kM6Ri4G4LfQGJcyMpfMPEA1herPuH", "name": "go-libp2p-circuit", - "version": "2.2.2" + "version": "2.2.6" }, { "author": "magik6k", - "hash": "QmaUU1Hu8pbR2NiTJ1NHVBcNTQR499AJVMkkAoRqhdxbgz", + "hash": "QmaixNkKwtinV3umL5VD1VDD5CQjnZhXY31awM2YHTzbui", "name": "go-ds-badger", - "version": "1.8.0" + "version": "1.10.0" }, { "author": "whyrusleeping", @@ -368,21 +368,21 @@ }, { "author": "whyrusleeping", - "hash": "QmSw6zWpuKvcHne7AjNS3LdmcPm1iUq5qd1z1KgVib7QnM", + "hash": "QmZygFpFQfDwTNeU8AYTfEgAXfb7yfuQh9L4wYG7GgtcMH", "name": "go-libp2p-connmgr", - "version": "0.3.19" + "version": "0.3.21" }, { "author": "why", - "hash": "QmV9T3rTezwJhMJQBzVrGj2tncJwv23dTKdxzXrUxAvWFi", + "hash": "QmXPqoktJEKkWPT6rSdhCM2G3E1yR7uUBdjnJrhJYeBgHU", "name": "go-libp2p-interface-connmgr", - "version": "0.0.16" + "version": "0.0.18" }, { "author": "why", - "hash": "QmSzdvo9aPzLj4HXWTcgGAp8N84tZc8LbLmFZFwUb1dpWk", + "hash": "QmesXvbRGyKQn1XbPHx1Mr5E6RTJYR9c8zwFVuGZq9Aa1j", "name": "go-ipfs-addr", - "version": "0.1.23" + "version": "0.1.24" }, { "author": "The Go Authors", @@ -404,9 +404,9 @@ }, { "author": "hsanjuan", - "hash": "QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p", + "hash": "QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f", "name": "go-ipfs-chunker", - "version": "0.1.1" + "version": "0.1.2" }, { "author": "jbenet", @@ -416,21 +416,21 @@ }, { "author": "hsanjuan", - "hash": "QmUDTSi6zJ6ACyQaKtxscCUxrg5DaXs9r4RQUPFQXGPHpo", + "hash": "QmS73grfbWgWrNztd8Lns9GCG3jjRNDfcPYg2VYQzKDZSt", "name": "go-ipfs-ds-help", - "version": "0.1.2" - }, - { - "author": "hsanjuan", - "hash": "QmScZySgru9jaoDa12sSfvh21sWbqF5eXkieTmJzAHJXkQ", - "name": "go-ipfs-routing", "version": "0.1.3" }, { "author": "hsanjuan", - "hash": "QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC", + "hash": "QmQqPdGQfsfQTpRUUzgD3d2RzWHJffZsSqwopnZ2BkiezW", + "name": "go-ipfs-routing", + "version": "0.1.5" + }, + { + "author": "hsanjuan", + "hash": "QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR", "name": "go-ipfs-blockstore", - "version": "0.1.2" + "version": "0.1.4" }, { "author": "whyrusleeping", @@ -458,21 +458,21 @@ }, { "author": "hsanjuan", - "hash": "QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw", + "hash": "QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb", "name": "go-ipfs-exchange-offline", - "version": "0.1.2" + "version": "0.1.3" }, { "author": "stebalien", - "hash": "QmPbLCBNGvyQhs3xK64cbobq7sN1Hdn6Ud9pkhsZME1sqT", + "hash": "QmbyoYqzgpaKt97AEoAx4zJCuHdQ71GNkpVZwhJ1wUtzba", "name": "go-libp2p-pubsub-router", - "version": "0.4.5" + "version": "0.4.9" }, { "author": "Stebalien", - "hash": "QmcRdSdYkL17qhuQAibF5D14XdQ1iunvaVnXGjDiQTdRm9", + "hash": "QmfGNszPuruiURVbgyvoj7eoVe9bkj2uHugMZVteX9zxD1", "name": "go-libp2p-routing-helpers", - "version": "0.3.4" + "version": "0.3.6" }, { "author": "fsnotify", @@ -482,9 +482,9 @@ }, { "author": "stebalien", - "hash": "QmZrmn2BPZbSviQAWeyY2iXkCukmJHv9n7zrLgWU5KgbTb", + "hash": "QmWhm9qS3NZdvTgAsB1cX4q9UbNu8yFybCcAMchCN88w7o", "name": "go-ipns", - "version": "0.1.9" + "version": "0.1.11" }, { "author": "whyrusleeping", @@ -494,39 +494,39 @@ }, { "author": "why", - "hash": "QmUdtRsAr9RYxqNwUzeHDhv5bnVppiHLixP1SU4YysVj2S", + "hash": "QmQHbKeMWRNT8koMhh2DrTXZWepYVoGPNXni6JG1L3BhGq", "name": "go-bitswap", - "version": "1.1.3" + "version": "1.1.7" }, { "author": "why", - "hash": "QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe", + "hash": "QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ", "name": "go-blockservice", - "version": "1.1.3" + "version": "1.1.7" }, { "author": "why", - "hash": "QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV", + "hash": "QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd", "name": "go-merkledag", - "version": "1.1.3" + "version": "1.1.7" }, { "author": "why", - "hash": "QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2", + "hash": "QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx", "name": "go-path", - "version": "1.1.3" + "version": "1.1.7" }, { "author": "why", - "hash": "QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46", + "hash": "QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf", "name": "go-unixfs", - "version": "1.1.3" + "version": "1.1.7" }, { "author": "magik6k", - "hash": "QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk", + "hash": "QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u", "name": "go-ipfs-config", - "version": "0.2.9" + "version": "0.2.13" }, { "author": "why", @@ -536,9 +536,9 @@ }, { "author": "hsanjuan", - "hash": "QmahrY1adY4wvtYEtoGjpZ2GUohTyukrkMkwUR9ytRjTG2", + "hash": "QmPbuswDwcPT4WquGqGoeBBDuuBaUmbZJFYiaes6vkgXYJ", "name": "go-mfs", - "version": "0.1.3" + "version": "0.1.7" }, { "author": "kevina", @@ -554,9 +554,9 @@ }, { "author": "marten-seemann", - "hash": "QmPWMfcxNC7txnUvT21xdivgRJfJ9e7YuC5nCn6JEALFQv", + "hash": "QmbxTJyyqtyYYM7wLHWv529e2dwzt9a9o8FfVQALvPpadC", "name": "go-libp2p-quic-transport", - "version": "0.2.5" + "version": "0.2.7" }, { "author": "mitchellh", diff --git a/pin/gc/gc.go b/pin/gc/gc.go index f5ca72547..c392eee9d 100644 --- a/pin/gc/gc.go +++ b/pin/gc/gc.go @@ -8,16 +8,16 @@ import ( "strings" pin "github.com/ipfs/go-ipfs/pin" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - dstore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" "gx/ipfs/QmVkMRSkXrpjqrroEXWuYBvDBnXCdMMY6gsKicBGVGUqKT/go-verifcid" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" + dstore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" ) var log = logging.Logger("gc") diff --git a/pin/pin.go b/pin/pin.go index cadc4530a..4b91fa407 100644 --- a/pin/pin.go +++ b/pin/pin.go @@ -10,11 +10,11 @@ import ( "time" "github.com/ipfs/go-ipfs/dagutils" - mdag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + mdag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -228,16 +228,28 @@ func (p *pinner) Pin(ctx context.Context, node ipld.Node, recurse bool) error { if p.directPin.Has(c) { p.directPin.Remove(c) } - + p.lock.Unlock() // fetch entire graph err := mdag.FetchGraph(ctx, c, p.dserv) + p.lock.Lock() if err != nil { return err } + if p.recursePin.Has(c) { + return nil + } + + if p.directPin.Has(c) { + p.directPin.Remove(c) + } + p.recursePin.Add(c) } else { - if _, err := p.dserv.Get(ctx, c); err != nil { + p.lock.Unlock() + _, err := p.dserv.Get(ctx, c) + p.lock.Lock() + if err != nil { return err } diff --git a/pin/pin_test.go b/pin/pin_test.go index 2549084f5..91efc24b6 100644 --- a/pin/pin_test.go +++ b/pin/pin_test.go @@ -5,15 +5,15 @@ import ( "testing" "time" - mdag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bs "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + mdag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bs "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" util "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dssync "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/sync" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dssync "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/sync" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) var rand = util.NewTimeSeededRand() diff --git a/pin/set.go b/pin/set.go index 9b4446e37..0b50c23a0 100644 --- a/pin/set.go +++ b/pin/set.go @@ -10,7 +10,7 @@ import ( "sort" "github.com/ipfs/go-ipfs/pin/internal/pb" - "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" + "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" diff --git a/pin/set_test.go b/pin/set_test.go index e366eac70..1fcfb1ad1 100644 --- a/pin/set_test.go +++ b/pin/set_test.go @@ -5,14 +5,14 @@ import ( "encoding/binary" "testing" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - bserv "gx/ipfs/QmcRecCZWM2NZfCQrCe97Ch3Givv8KKEP82tGUDntzdLFe/go-blockservice" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" + bserv "gx/ipfs/QmY1fUNoXjC8sH86kyaK8BWFGaU6MmH4AJfF1w4sKjmtRZ/go-blockservice" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - offline "gx/ipfs/QmR5miWuikPxWyUrzMYJVmFUcD44pGdtc98h9Qsbp4YcJw/go-ipfs-exchange-offline" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - dsq "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/query" - blockstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + offline "gx/ipfs/QmT6dHGp3UYd3vUMpy7rzX2CXQv7HLcj42Vtq8qwwjgASb/go-ipfs-exchange-offline" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + dsq "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/query" + blockstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) func ignoreCids(_ cid.Cid) {} diff --git a/plugin/datastore.go b/plugin/datastore.go new file mode 100644 index 000000000..735eedc9d --- /dev/null +++ b/plugin/datastore.go @@ -0,0 +1,14 @@ +package plugin + +import ( + "github.com/ipfs/go-ipfs/repo/fsrepo" +) + +// PluginDatastore is an interface that can be implemented to add handlers for +// for different datastores +type PluginDatastore interface { + Plugin + + DatastoreTypeName() string + DatastoreConfigParser() fsrepo.ConfigFromMap +} diff --git a/plugin/loader/initializer.go b/plugin/loader/initializer.go index 10e0fc112..9d03dfeea 100644 --- a/plugin/loader/initializer.go +++ b/plugin/loader/initializer.go @@ -3,8 +3,9 @@ package loader import ( "github.com/ipfs/go-ipfs/core/coredag" "github.com/ipfs/go-ipfs/plugin" - "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go" + "github.com/ipfs/go-ipfs/repo/fsrepo" + "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) @@ -32,6 +33,11 @@ func run(plugins []plugin.Plugin) error { if err != nil { return err } + case plugin.PluginDatastore: + err := fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser()) + if err != nil { + return err + } default: panic(pl) } diff --git a/repo/fsrepo/config_test.go b/repo/fsrepo/config_test.go index e25ecfa8b..c514b6975 100644 --- a/repo/fsrepo/config_test.go +++ b/repo/fsrepo/config_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) // note: to test sorting of the mountpoints in the disk spec they are diff --git a/repo/fsrepo/datastores.go b/repo/fsrepo/datastores.go index 10d97efb8..d162c22b4 100644 --- a/repo/fsrepo/datastores.go +++ b/repo/fsrepo/datastores.go @@ -11,13 +11,13 @@ import ( repo "github.com/ipfs/go-ipfs/repo" humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" - levelds "gx/ipfs/QmPnXsHj9W8WpDDwj2iogRcnVL6d5ANtK9SAJLgKpeBMq8/go-ds-leveldb" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - mount "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore/mount" - flatfs "gx/ipfs/QmY8toEWLh1zpSCeQTP8kZDRm1dik3cck9p2miCK1QgaAi/go-ds-flatfs" - measure "gx/ipfs/QmYY98HGLuMUm7cLM8Afmvzzw6G5Md6s7pVW78Hd7hJAiA/go-ds-measure" - badgerds "gx/ipfs/QmaUU1Hu8pbR2NiTJ1NHVBcNTQR499AJVMkkAoRqhdxbgz/go-ds-badger" + measure "gx/ipfs/QmQS6UXi1R87y9nEgnCNmG6YfMzvBSLir7xUheMNFP3hoe/go-ds-measure" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" + mount "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore/mount" + badgerds "gx/ipfs/QmaixNkKwtinV3umL5VD1VDD5CQjnZhXY31awM2YHTzbui/go-ds-badger" ldbopts "gx/ipfs/QmbBhyDKsY4mbY6xsKt3qu9Y7FPvMJ6qbD8AMjYYvPRw1g/goleveldb/leveldb/opt" + flatfs "gx/ipfs/QmbYQHTSz4Sg4Y2Vyd7hftGgM1yXwSUBKb47VpoPRuP5Nc/go-ds-flatfs" + levelds "gx/ipfs/QmccqjKZUTqp4ikWNyAbjBuP5HEdqSqRuAr9mcEhYab54a/go-ds-leveldb" ) // ConfigFromMap creates a new datastore config from a map @@ -36,7 +36,12 @@ type DatastoreConfig interface { Create(path string) (repo.Datastore, error) } -// DiskSpec is the type returned by the DatastoreConfig's DiskSpec method +// DiskSpec is a minimal representation of the characteristic values of the +// datastore. If two diskspecs are the same, the loader assumes that they refer +// to exactly the same datastore. If they differ at all, it is assumed they are +// completely different datastores and a migration will be performed. Runtime +// values such as cache options or concurrency options should not be added +// here. type DiskSpec map[string]interface{} // Bytes returns a minimal JSON encoding of the DiskSpec @@ -68,6 +73,16 @@ func init() { } } +func AddDatastoreConfigHandler(name string, dsc ConfigFromMap) error { + _, ok := datastores[name] + if ok { + return fmt.Errorf("already have a datastore named %q", name) + } + + datastores[name] = dsc + return nil +} + // AnyDatastoreConfig returns a DatastoreConfig from a spec based on // the "type" parameter func AnyDatastoreConfig(params map[string]interface{}) (DatastoreConfig, error) { diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 2c1833f8f..ad2555d66 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -19,12 +19,12 @@ import ( dir "github.com/ipfs/go-ipfs/thirdparty/dir" util "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" - serialize "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config/serialize" - measure "gx/ipfs/QmYY98HGLuMUm7cLM8Afmvzzw6G5Md6s7pVW78Hd7hJAiA/go-ds-measure" + measure "gx/ipfs/QmQS6UXi1R87y9nEgnCNmG6YfMzvBSLir7xUheMNFP3hoe/go-ds-measure" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + serialize "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config/serialize" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" lockfile "gx/ipfs/Qmc4w3gm2TqoEbTYjpPs5FXP8DEB6cuvZWPy6bUTKiht7a/go-fs-lock" homedir "gx/ipfs/QmdcULN1WCzgoQmcCaUAmEhwcxHYsDrbZ2LvRJKCL8dMrK/go-homedir" ) diff --git a/repo/fsrepo/fsrepo_test.go b/repo/fsrepo/fsrepo_test.go index af30fa646..c27a09503 100644 --- a/repo/fsrepo/fsrepo_test.go +++ b/repo/fsrepo/fsrepo_test.go @@ -9,8 +9,8 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/assert" - datastore "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" + datastore "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" ) // swap arg order diff --git a/repo/fsrepo/misc.go b/repo/fsrepo/misc.go index cd4b3a8bb..f2ca5f828 100644 --- a/repo/fsrepo/misc.go +++ b/repo/fsrepo/misc.go @@ -3,7 +3,7 @@ package fsrepo import ( "os" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" homedir "gx/ipfs/QmdcULN1WCzgoQmcCaUAmEhwcxHYsDrbZ2LvRJKCL8dMrK/go-homedir" ) diff --git a/repo/mock.go b/repo/mock.go index 782dc5336..cf7986acb 100644 --- a/repo/mock.go +++ b/repo/mock.go @@ -6,7 +6,7 @@ import ( filestore "github.com/ipfs/go-ipfs/filestore" keystore "github.com/ipfs/go-ipfs/keystore" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" ) diff --git a/repo/repo.go b/repo/repo.go index abe945c47..50948965b 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -7,9 +7,9 @@ import ( filestore "github.com/ipfs/go-ipfs/filestore" keystore "github.com/ipfs/go-ipfs/keystore" - ds "gx/ipfs/QmUyz7JTJzgegC6tiJrfby3mPhzcdswVtG4x58TQ6pq8jV/go-datastore" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ma "gx/ipfs/QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7/go-multiaddr" + ds "gx/ipfs/QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D/go-datastore" ) var ( diff --git a/tar/format.go b/tar/format.go index 2bf7b6416..a24136369 100644 --- a/tar/format.go +++ b/tar/format.go @@ -9,13 +9,13 @@ import ( "strings" "github.com/ipfs/go-ipfs/dagutils" - importer "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/importer" - uio "gx/ipfs/QmU4x3742bvgfxJsByEDpBnifJqjJdV6x528co4hwKCn46/go-unixfs/io" - dag "gx/ipfs/QmcBoNcAP6qDjgRBew7yjvCqHq7p5jMstE44jPUBWBxzsV/go-merkledag" - path "gx/ipfs/QmcjwUb36Z16NJkvDX6ccXPqsFswo6AsRXynyXcLLCphV2/go-path" + importer "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/importer" + uio "gx/ipfs/QmQDcPcBH8nfz3JB4K4oEvxhRmBwCrMgvG966XpExEWexf/go-unixfs/io" + path "gx/ipfs/QmQmMu1vsgsjxyB8tzrA6ZTCTCLDLVaXMb4Q57r2v886Sx/go-path" + dag "gx/ipfs/QmXTw4By9FMZAt7qJm4JoJuNBrBgqMMzkS4AjKc4zqTUVd/go-merkledag" - chunker "gx/ipfs/QmULKgr55cSWR8Kiwy3cVRcAiGVnR6EVSaB7hJcWS4138p/go-ipfs-chunker" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" + chunker "gx/ipfs/QmbrQ27wGQeE8spxjbw9mk5Ef7as4tRFSnWLkEGg4xeg2f/go-ipfs-chunker" ipld "gx/ipfs/QmdDXJs4axxefSPgK6Y1QhpJWKuDPnGJiqgq4uncb4rFHL/go-ipld-format" ) diff --git a/test/bench/bench_cli_ipfs_add/main.go b/test/bench/bench_cli_ipfs_add/main.go index de034bded..fa3ca5d5b 100644 --- a/test/bench/bench_cli_ipfs_add/main.go +++ b/test/bench/bench_cli_ipfs_add/main.go @@ -13,7 +13,7 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/unit" random "gx/ipfs/QmSJ9n2s9NUoA9D849W5jj5SJ94nMcZpj1jCgQJieiNqSt/go-random" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) var ( diff --git a/test/bench/offline_add/main.go b/test/bench/offline_add/main.go index ede1114e1..21da737df 100644 --- a/test/bench/offline_add/main.go +++ b/test/bench/offline_add/main.go @@ -12,7 +12,7 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/unit" random "gx/ipfs/QmSJ9n2s9NUoA9D849W5jj5SJ94nMcZpj1jCgQJieiNqSt/go-random" - config "gx/ipfs/QmVBUpxsHh53rNcufqxMpLAmz37eGyLJUaexDy1W9YkiNk/go-ipfs-config" + config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" ) func main() { diff --git a/test/integration/addcat_test.go b/test/integration/addcat_test.go index 2e83dfcf9..d8de70d1e 100644 --- a/test/integration/addcat_test.go +++ b/test/integration/addcat_test.go @@ -12,15 +12,17 @@ import ( "time" "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" + "github.com/ipfs/go-ipfs/core/coreapi/interface" coreunix "github.com/ipfs/go-ipfs/core/coreunix" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" random "gx/ipfs/QmSJ9n2s9NUoA9D849W5jj5SJ94nMcZpj1jCgQJieiNqSt/go-random" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" logging "gx/ipfs/QmZChCsSt8DctjceaL56Eibc29CVQq4dGKRXC5JRZ6Ppae/go-log" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" ) var log = logging.Logger("epictest") @@ -118,6 +120,8 @@ func DirectAddCat(data []byte, conf testutil.LatencyConfig) error { } defer catter.Close() + catterApi := coreapi.NewCoreAPI(catter) + err = mn.LinkAll() if err != nil { return err @@ -138,7 +142,12 @@ func DirectAddCat(data []byte, conf testutil.LatencyConfig) error { return err } - readerCatted, err := coreunix.Cat(ctx, catter, added) + ap, err := iface.ParsePath(added) + if err != nil { + return err + } + + readerCatted, err := catterApi.Unixfs().Cat(ctx, ap) if err != nil { return err } diff --git a/test/integration/bench_cat_test.go b/test/integration/bench_cat_test.go index 794a49558..47620497e 100644 --- a/test/integration/bench_cat_test.go +++ b/test/integration/bench_cat_test.go @@ -9,13 +9,15 @@ import ( "testing" "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" + "github.com/ipfs/go-ipfs/core/coreapi/interface" coreunix "github.com/ipfs/go-ipfs/core/coreunix" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ) func BenchmarkCat1MB(b *testing.B) { benchmarkVarCat(b, unit.MB*1) } @@ -64,6 +66,8 @@ func benchCat(b *testing.B, data []byte, conf testutil.LatencyConfig) error { } defer catter.Close() + catterApi := coreapi.NewCoreAPI(catter) + err = mn.LinkAll() if err != nil { return err @@ -84,8 +88,13 @@ func benchCat(b *testing.B, data []byte, conf testutil.LatencyConfig) error { return err } + ap, err := iface.ParsePath(added) + if err != nil { + return err + } + b.StartTimer() - readerCatted, err := coreunix.Cat(ctx, catter, added) + readerCatted, err := catterApi.Unixfs().Cat(ctx, ap) if err != nil { return err } diff --git a/test/integration/bitswap_wo_routing_test.go b/test/integration/bitswap_wo_routing_test.go index 492101f1a..73723ca11 100644 --- a/test/integration/bitswap_wo_routing_test.go +++ b/test/integration/bitswap_wo_routing_test.go @@ -10,7 +10,7 @@ import ( "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" ) func TestBitswapWithoutRouting(t *testing.T) { diff --git a/test/integration/three_legged_cat_test.go b/test/integration/three_legged_cat_test.go index 20197d430..d478e6357 100644 --- a/test/integration/three_legged_cat_test.go +++ b/test/integration/three_legged_cat_test.go @@ -10,13 +10,15 @@ import ( "time" core "github.com/ipfs/go-ipfs/core" + "github.com/ipfs/go-ipfs/core/coreapi" + "github.com/ipfs/go-ipfs/core/coreapi/interface" coreunix "github.com/ipfs/go-ipfs/core/coreunix" mock "github.com/ipfs/go-ipfs/core/mock" "github.com/ipfs/go-ipfs/thirdparty/unit" testutil "gx/ipfs/QmNfQbgBfARAtrYsBguChX6VJ5nbjeoYy1KdC36aaYWqG8/go-testutil" - mocknet "gx/ipfs/QmVsVARb86uSe1qYouewFMNd2p2sp2NGWm1JGPReVDWchW/go-libp2p/p2p/net/mock" - pstore "gx/ipfs/QmfAQMFpgDU2U4BXG64qVr8HSiictfWvkSBz7Y2oDj65st/go-libp2p-peerstore" + mocknet "gx/ipfs/QmU9Cf9q5TBCAC3kg74Fqr6K7DQTwa41C44YypYqB2GfR8/go-libp2p/p2p/net/mock" + pstore "gx/ipfs/QmXEyLwySuDMXejWBu8XwdkX2WuGKk8x9jFwz8js7j72UX/go-libp2p-peerstore" ) func TestThreeLeggedCatTransfer(t *testing.T) { @@ -100,6 +102,9 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { return err } defer catter.Close() + + catterApi := coreapi.NewCoreAPI(catter) + mn.LinkAll() bis := bootstrap.Peerstore.PeerInfo(bootstrap.PeerHost.ID()) @@ -116,7 +121,12 @@ func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error { return err } - readerCatted, err := coreunix.Cat(ctx, catter, added) + ap, err := iface.ParsePath(added) + if err != nil { + return err + } + + readerCatted, err := catterApi.Unixfs().Cat(ctx, ap) if err != nil { return err } diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index 8a54a6abf..05cfc57d1 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -199,8 +199,11 @@ test_set_address_vars() { ' if ipfs swarm addrs local >/dev/null 2>&1; then + test_expect_success "get swarm addresses" ' + ipfs swarm addrs local > addrs_out + ' + test_expect_success "set swarm address vars" ' - ipfs swarm addrs local > addrs_out && SWARM_MADDR=$(grep "127.0.0.1" addrs_out) && SWARM_PORT=$(port_from_maddr $SWARM_MADDR) ' diff --git a/test/sharness/t0040-add-and-cat.sh b/test/sharness/t0040-add-and-cat.sh index 0ee4477cd..ee3663ad3 100755 --- a/test/sharness/t0040-add-and-cat.sh +++ b/test/sharness/t0040-add-and-cat.sh @@ -156,15 +156,34 @@ test_add_cat_file() { test_cmp expected actual ' + test_expect_success "ipfs add --chunker size-64 succeeds" ' + ipfs add --chunker=size-64 mountdir/hello.txt >actual + ' + + test_expect_success "ipfs add --chunker size-64 output looks good" ' + HASH="QmVr26fY1tKyspEJBniVhqxQeEjhF78XerGiqWAwraVLQH" && + echo "added $HASH hello.txt" >expected && + test_cmp expected actual + ' + + test_expect_success "ipfs add --chunker=size-0 failed" ' + test_expect_code 1 ipfs add -Q --chunker=size-0 mountdir/hello.txt + ' + test_expect_success "ipfs add --chunker rabin-36-512-1024 succeeds" ' - ipfs add -Q --chunker rabin-36-512-1024 mountdir/hello.txt + ipfs add --chunker rabin-36-512-1024 mountdir/hello.txt >actual + ' + + test_expect_success "ipfs add --chunker rabin-36-512-1024 output looks good" ' + HASH="QmVr26fY1tKyspEJBniVhqxQeEjhF78XerGiqWAwraVLQH" && + echo "added $HASH hello.txt" >expected && + test_cmp expected actual ' test_expect_success "ipfs add --chunker rabin-12-512-1024 failed" ' test_expect_code 1 ipfs add -Q --chunker rabin-12-512-1024 mountdir/hello.txt ' - test_expect_success "ipfs add on hidden file succeeds" ' echo "Hello Worlds!" >mountdir/.hello.txt && ipfs add mountdir/.hello.txt >actual diff --git a/test/sharness/t0052-object-diff.sh b/test/sharness/t0052-object-diff.sh index 949088c27..e512c4b18 100755 --- a/test/sharness/t0052-object-diff.sh +++ b/test/sharness/t0052-object-diff.sh @@ -15,16 +15,22 @@ test_expect_success "create some objects for testing diffs" ' echo "stuff" > foo/bar && mkdir foo/baz && A=$(ipfs add -r -q foo | tail -n1) && + AR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "more things" > foo/cat && B=$(ipfs add -r -q foo | tail -n1) && + BR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "nested" > foo/baz/dog && C=$(ipfs add -r -q foo | tail -n1) + CR=$(ipfs add --raw-leaves -r -q foo | tail -n1) echo "changed" > foo/bar && D=$(ipfs add -r -q foo | tail -n1) && + DR=$(ipfs add --raw-leaves -r -q foo | tail -n1) && echo "" > single_file && SINGLE_FILE=$(ipfs add -r -q single_file | tail -n1) && + SINGLE_FILE_RAW=$(ipfs add --raw-leaves -r -q single_file | tail -n1) && mkdir empty_dir EMPTY_DIR=$(ipfs add -r -q empty_dir | tail -n1) + EMPTY_DIR_RAW=$(ipfs add --raw-leaves -r -q empty_dir | tail -n1) ' test_expect_success "diff against self is empty" ' @@ -36,18 +42,39 @@ test_expect_success "identity diff output looks good" ' test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) against self is empty" ' + ipfs object diff $AR $AR > diff_raw_out +' + +test_expect_success "identity diff (raw-leaves) output looks good" ' + printf "" > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff against self (single file) is empty" ' - ipfs object diff $SINGLE_FILE $SINGLE_FILE > diff_out + ipfs object diff $SINGLE_FILE $SINGLE_FILE > diff_out && printf "" > diff_exp && test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) against self (single file) is empty" ' + ipfs object diff $SINGLE_FILE_RAW $SINGLE_FILE_RAW > diff_raw_out && + printf "" > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff against self (empty dir) is empty" ' - ipfs object diff $EMPTY_DIR $EMPTY_DIR > diff_out + ipfs object diff $EMPTY_DIR $EMPTY_DIR > diff_out && printf "" > diff_exp && test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) against self (empty dir) is empty" ' + ipfs object diff $EMPTY_DIR_RAW $EMPTY_DIR_RAW > diff_raw_out && + printf "" > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff added link works" ' ipfs object diff $A $B > diff_out ' @@ -57,6 +84,15 @@ test_expect_success "diff added link looks right" ' test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) added link works" ' + ipfs object diff $AR $BR > diff_raw_out +' + +test_expect_success "diff (raw-leaves) added link looks right" ' + echo + zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4 \"cat\" > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "verbose diff added link works" ' ipfs object diff -v $A $B > diff_out ' @@ -66,6 +102,15 @@ test_expect_success "verbose diff added link looks right" ' test_cmp diff_exp diff_out ' +test_expect_success "verbose diff (raw-leaves) added link works" ' + ipfs object diff -v $AR $BR > diff_raw_out +' + +test_expect_success "verbose diff (raw-leaves) added link looks right" ' + echo Added new link \"cat\" pointing to zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4. > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff removed link works" ' ipfs object diff -v $B $A > diff_out ' @@ -75,6 +120,15 @@ test_expect_success "diff removed link looks right" ' test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) removed link works" ' + ipfs object diff -v $BR $AR > diff_raw_out +' + +test_expect_success "diff (raw-leaves) removed link looks right" ' + echo Removed link \"cat\" \(was zb2rhmWNFDCdMjJoCZPE5b5NuU38yoRzRmEtfzb4exxk3R8g4\). > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff nested add works" ' ipfs object diff -v $B $C > diff_out ' @@ -84,6 +138,15 @@ test_expect_success "diff looks right" ' test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) nested add works" ' + ipfs object diff -v $BR $CR > diff_raw_out +' + +test_expect_success "diff (raw-leaves) looks right" ' + echo Added new link \"baz/dog\" pointing to zb2rhaM8wjDfi8A22dEqk89raWtViq8pjxvKQu2eaKtWhYKgE. > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_expect_success "diff changed link works" ' ipfs object diff -v $C $D > diff_out ' @@ -93,4 +156,13 @@ test_expect_success "diff looks right" ' test_cmp diff_exp diff_out ' +test_expect_success "diff (raw-leaves) changed link works" ' + ipfs object diff -v $CR $DR > diff_raw_out +' + +test_expect_success "diff(raw-leaves) looks right" ' + echo Changed \"bar\" from zb2rhdUECGnPgMJNgmghaMKdqqGdpTe9GmEJiPna488ThfLBz to zb2rhfEA1M13SPoeayrsPcKhCezgMQPjguGFLH56G8qQ2qpDn. > diff_raw_exp && + test_cmp diff_raw_exp diff_raw_out +' + test_done diff --git a/test/sharness/t0180-p2p.sh b/test/sharness/t0180-p2p.sh index 544cd1f6f..0d676746c 100755 --- a/test/sharness/t0180-p2p.sh +++ b/test/sharness/t0180-p2p.sh @@ -24,7 +24,8 @@ check_test_ports() { test_expect_success "test ports are closed" ' (! (netstat -lnp | grep "LISTEN" | grep ":10101 ")) && (! (netstat -lnp | grep "LISTEN" | grep ":10102 "))&& - (! (netstat -lnp | grep "LISTEN" | grep ":10103 ")) + (! (netstat -lnp | grep "LISTEN" | grep ":10103 ")) && + (! (netstat -lnp | grep "LISTEN" | grep ":10104 ")) ' } check_test_ports @@ -73,10 +74,27 @@ test_server_to_client() { spawn_sending_server -test_expect_success 'S->C Setup client side' ' +test_expect_success 'S->C(/ipfs/peerID) Setup client side' ' ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10102 /ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log ' +test_expect_success 'S->C Setup(dnsaddr/addr/ipfs/peerID) client side' ' + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10103 /dnsaddr/bootstrap.libp2p.io/ipfs/${PEERID_0} 2>&1 > dialer-stdouterr.log +' + +test_expect_success 'S->C Setup(dnsaddr/addr) client side' ' + ipfsi 1 p2p forward /x/p2p-test /ip4/127.0.0.1/tcp/10104 /dnsaddr/bootstrap.libp2p.io/ 2>&1 > dialer-stdouterr.log +' + + +test_expect_success 'S->C Output is empty' ' + test_must_be_empty dialer-stdouterr.log +' + +test_expect_success "'ipfs p2p ls | grep' succeeds" ' + ipfsi 1 p2p ls | grep "/x/p2p-test /ip4/127.0.0.1/tcp/10104" +' + test_server_to_client test_expect_success 'S->C Connect with dead server' ' diff --git a/test/sharness/t0250-files-api.sh b/test/sharness/t0250-files-api.sh index 7b97f31de..793e168be 100755 --- a/test/sharness/t0250-files-api.sh +++ b/test/sharness/t0250-files-api.sh @@ -629,6 +629,20 @@ test_files_api() { test_expect_success "repo gc $EXTRA" ' ipfs repo gc ' + + # test rm + + test_expect_success "remove file forcibly" ' + echo "hello world" | ipfs files write --create /forcibly && + ipfs files rm --force /forcibly && + verify_dir_contents / + ' + + test_expect_success "remove directory forcibly" ' + ipfs files mkdir /forcibly-dir && + ipfs files rm --force /forcibly-dir && + verify_dir_contents / + ' } # test offline and online diff --git a/test/sharness/t0290-cid.sh b/test/sharness/t0290-cid.sh new file mode 100755 index 000000000..ecc2ba19e --- /dev/null +++ b/test/sharness/t0290-cid.sh @@ -0,0 +1,228 @@ +#!/usr/bin/env bash + +test_description="Test cid commands" + +. lib/test-lib.sh + +# note: all "ipfs cid" commands should work without requiring a repo + +CIDv0="QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv" +CIDv1="zdj7WZAAFKPvYPPzyJLso2hhxo8a7ZACFQ4DvvfrNXTHidofr" +CIDb32="bafybeibxm2nsadl3fnxv2sxcxmxaco2jl53wpeorjdzidjwf5aqdg7wa6u" + +test_expect_success "cid base32 works" ' + echo $CIDb32 > expected && + ipfs cid base32 $CIDv0 > actual1 && + test_cmp actual1 expected && + ipfs cid base32 $CIDv1 > actual2 && + test_cmp expected actual2 +' + +test_expect_success "cid format -v 1 -b base58btc" ' + echo $CIDv1 > expected && + ipfs cid format -v 1 -b base58btc $CIDv0 > actual1 && + test_cmp actual1 expected && + ipfs cid format -v 1 -b base58btc $CIDb32 > actual2 && + test_cmp expected actual2 +' + +cat < various_cids +QmZZRTyhDpL5Jgift1cHbAhexeE1m2Hw8x8g7rTcPahDvo + QmPhk6cJkRcFfZCdYam4c9MKYjFG9V29LswUnbrFNhtk2S +bafybeihtwdtifv43rn5cyilnmkwofdcxi2suqimmo62vn3etf45gjoiuwy +bafybeiek4tfxkc4ov6jsmb63fzbirrsalnjw24zd5xawo2fgxisd4jmpyq +zdj7WgYfT2gfsgiUxzPYboaRbP9H9CxZE5jVMK9pDDwCcKDCR +zdj7WbTaiJT1fgatdet9Ei9iDB5hdCxkbVyhyh8YTUnXMiwYi +uAXASIDsp4T3Wnd6kXFOQaljH3GFK_ixkjMtVhB9VOBrPK3bp + uAXASIDdmmyANeytvXUriuy4BO0lfd2eR0UjygabF6CAzfsD1 +EOF + +cat < various_cids_base32 +bafybeifgwyq5gs4l2mru5klgwjfmftjvkmbyyjurbupuz2bst7mhmg2hwa +bafybeiauil46g3lb32jemjbl7yspca3twdcg4wwkbsgdgvgdj5fpfv2f64 +bafybeihtwdtifv43rn5cyilnmkwofdcxi2suqimmo62vn3etf45gjoiuwy +bafybeiek4tfxkc4ov6jsmb63fzbirrsalnjw24zd5xawo2fgxisd4jmpyq +bafybeifffq3aeaymxejo37sn5fyaf7nn7hkfmzwdxyjculx3lw4tyhk7uy +bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354 +bafybeib3fhqt3vu532sfyu4qnjmmpxdbjl7cyzemznkyih2vhanm6k3w5e +bafybeibxm2nsadl3fnxv2sxcxmxaco2jl53wpeorjdzidjwf5aqdg7wa6u +EOF + +cat < various_cids_v1 +zdj7WgefqQm5HogBQ2bckZuTYYDarRTUZi51GYCnerHD2G86j +zdj7WWnzU3Nbu5rYGWZHKigUXBtAwShs2SHDCM1TQEvC9TeCN +zdj7WmqAbpsfXgiRBtZP1oAP9QWuuY3mqbc5JhpxJkfT3vYCu +zdj7Wen5gtfr7AivXip3zYd1peuq2QfKrqAn4FGiciVWb96YB +zdj7WgYfT2gfsgiUxzPYboaRbP9H9CxZE5jVMK9pDDwCcKDCR +zdj7WbTaiJT1fgatdet9Ei9iDB5hdCxkbVyhyh8YTUnXMiwYi +zdj7WZQrAvnY5ge3FNg5cmCsNwsvpYjdtu2yEmnWYQ4ES7Nzk +zdj7WZAAFKPvYPPzyJLso2hhxo8a7ZACFQ4DvvfrNXTHidofr +EOF + +test_expect_success "cid base32 works from stdin" ' + cat various_cids | ipfs cid base32 > actual && + test_cmp various_cids_base32 actual +' + +test_expect_success "cid format -v 1 -b base58btc works from stdin" ' + cat various_cids | ipfs cid format -v 1 -b base58btc > actual && + test_cmp various_cids_v1 actual +' + +cat < bases_expect + 0 identity +b 98 base32 +B 66 base32upper +c 99 base32pad +C 67 base32padupper +f 102 base16 +F 70 base16upper +m 109 base64 +M 77 base64pad +t 116 base32hexpad +T 84 base32hexpadupper +u 117 base64url +U 85 base64urlpad +v 118 base32hex +V 86 base32hexupper +z 122 base58btc +Z 90 base58flickr +EOF + +cat < codecs_expect + 85 raw + 112 protobuf + 113 cbor + 120 git-raw + 144 eth-block + 145 eth-block-list + 146 eth-tx-trie + 147 eth-tx + 148 eth-tx-receipt-trie + 149 eth-tx-receipt + 150 eth-state-trie + 151 eth-account-snapshot + 152 eth-storage-trie + 176 bitcoin-block + 177 bitcoin-tx + 192 zcash-block + 193 zcash-tx + 224 decred-block + 225 decred-tx +EOF + +cat < hashes_expect + 0 id + 17 sha1 + 18 sha2-256 + 19 sha2-512 + 20 sha3-512 + 21 sha3-384 + 22 sha3-256 + 23 sha3-224 + 25 shake-256 + 26 keccak-224 + 27 keccak-256 + 28 keccak-384 + 29 keccak-512 + 86 dbl-sha2-256 +45588 blake2b-160 +45589 blake2b-168 +45590 blake2b-176 +45591 blake2b-184 +45592 blake2b-192 +45593 blake2b-200 +45594 blake2b-208 +45595 blake2b-216 +45596 blake2b-224 +45597 blake2b-232 +45598 blake2b-240 +45599 blake2b-248 +45600 blake2b-256 +45601 blake2b-264 +45602 blake2b-272 +45603 blake2b-280 +45604 blake2b-288 +45605 blake2b-296 +45606 blake2b-304 +45607 blake2b-312 +45608 blake2b-320 +45609 blake2b-328 +45610 blake2b-336 +45611 blake2b-344 +45612 blake2b-352 +45613 blake2b-360 +45614 blake2b-368 +45615 blake2b-376 +45616 blake2b-384 +45617 blake2b-392 +45618 blake2b-400 +45619 blake2b-408 +45620 blake2b-416 +45621 blake2b-424 +45622 blake2b-432 +45623 blake2b-440 +45624 blake2b-448 +45625 blake2b-456 +45626 blake2b-464 +45627 blake2b-472 +45628 blake2b-480 +45629 blake2b-488 +45630 blake2b-496 +45631 blake2b-504 +45632 blake2b-512 +45652 blake2s-160 +45653 blake2s-168 +45654 blake2s-176 +45655 blake2s-184 +45656 blake2s-192 +45657 blake2s-200 +45658 blake2s-208 +45659 blake2s-216 +45660 blake2s-224 +45661 blake2s-232 +45662 blake2s-240 +45663 blake2s-248 +45664 blake2s-256 +EOF + +test_expect_success "cid bases" ' + cut -c 10- bases_expect > expect && + ipfs cid bases > actual && + test_cmp expect actual +' + +test_expect_success "cid bases --prefix" ' + cut -c 1-3,10- bases_expect > expect && + ipfs cid bases --prefix > actual && + test_cmp expect actual +' + +test_expect_success "cid bases --prefix --numeric" ' + ipfs cid bases --prefix --numeric > actual && + test_cmp bases_expect actual +' + +test_expect_success "cid codecs" ' + cut -c 8- codecs_expect > expect && + ipfs cid codecs > actual + test_cmp expect actual +' + +test_expect_success "cid codecs --numeric" ' + ipfs cid codecs --numeric > actual && + test_cmp codecs_expect actual +' + +test_expect_success "cid hashes" ' + cut -c 8- hashes_expect > expect && + ipfs cid hashes > actual + test_cmp expect actual +' + +test_expect_success "cid hashes --numeric" ' + ipfs cid hashes --numeric > actual && + test_cmp hashes_expect actual +' + +test_done diff --git a/test/sharness/t0600-issues-and-regressions-online.sh b/test/sharness/t0600-issues-and-regressions-online.sh index 6227968de..7cc66019c 100755 --- a/test/sharness/t0600-issues-and-regressions-online.sh +++ b/test/sharness/t0600-issues-and-regressions-online.sh @@ -59,5 +59,29 @@ test_expect_success "ipfs daemon --offline --mount fails - #2995" ' test_fsh cat daemon_err ' +test_launch_ipfs_daemon --offline + +test_expect_success "'ipfs name resolve' succeeds after ipfs id when daemon offline" ' + PEERID=`ipfs id --format=""` && + test_check_peerid "${PEERID}" && + ipfs name publish --allow-offline -Q "/ipfs/$HASH_WELCOME_DOCS" >publish_out +' + +test_expect_success "pubrmlish --quieter output looks good" ' + echo "${PEERID}" >expected1 && + test_cmp expected1 publish_out +' + +test_expect_success "'ipfs name resolve' succeeds" ' + ipfs name resolve "$PEERID" >output +' + +test_expect_success "resolve output looks good" ' + printf "/ipfs/%s\n" "$HASH_WELCOME_DOCS" >expected2 && + test_cmp expected2 output +' + +test_kill_ipfs_daemon + test_done diff --git a/thirdparty/cidv0v1/blockstore.go b/thirdparty/cidv0v1/blockstore.go index 2cb19a4f9..e6fc9169f 100644 --- a/thirdparty/cidv0v1/blockstore.go +++ b/thirdparty/cidv0v1/blockstore.go @@ -4,7 +4,7 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" - bs "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + bs "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) type blockstore struct { diff --git a/thirdparty/verifbs/verifbs.go b/thirdparty/verifbs/verifbs.go index 4ef906c39..cc2f34726 100644 --- a/thirdparty/verifbs/verifbs.go +++ b/thirdparty/verifbs/verifbs.go @@ -4,7 +4,7 @@ import ( cid "gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid" blocks "gx/ipfs/QmRcHuYzAyswytBuMF78rj3LTChYszomRFXNg4685ZN1WM/go-block-format" "gx/ipfs/QmVkMRSkXrpjqrroEXWuYBvDBnXCdMMY6gsKicBGVGUqKT/go-verifcid" - bstore "gx/ipfs/QmdriVJgKx4JADRgh3cYPXqXmsa1A45SvFki1nDWHhQNtC/go-ipfs-blockstore" + bstore "gx/ipfs/QmcDDgAXDbpDUpadCJKLr49KYR4HuL7T8Z1dZTHt6ixsoR/go-ipfs-blockstore" ) type VerifBSGC struct {