mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-25 04:17:44 +08:00
Merge branch 'master' into feat/namestream
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
This commit is contained in:
commit
0bef4603e8
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
|
||||
@ -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},
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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{},
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -126,6 +126,12 @@ It outputs to stdout, and <key> 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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
364
core/commands/cid.go
Normal file
364
core/commands/cid.go
Normal file
@ -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 <cid>'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 }
|
||||
@ -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"
|
||||
)
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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{})
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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 = `<hash>
|
||||
const (
|
||||
defaultStatFormat = `<hash>
|
||||
Size: <size>
|
||||
CumulativeSize: <cumulsize>
|
||||
ChildBlocks: <childs>
|
||||
Type: <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: "+
|
||||
"<hash> <size> <cumulsize> <type> <childs>. Conflicts with other format options.").WithDefault(defaultStatFormat),
|
||||
cmdkit.BoolOption("hash", "Print only hash. Implies '--format=<hash>'. Conflicts with other format options."),
|
||||
cmdkit.BoolOption("size", "Print only size. Implies '--format=<cumulsize>'. 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=<hash>'. Conflicts with other format options."),
|
||||
cmdkit.BoolOption(filesSizeOptionName, "Print only size. Implies '--format=<cumulsize>'. 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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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 <ipfs-path> 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 <ipfs-path> 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")
|
||||
}
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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: <src> <dst> <linkname>.").WithDefault("<dst>"),
|
||||
cmdkit.BoolOption("edges", "e", "Emit edge format: `<from> -> <to>`."),
|
||||
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: <src> <dst> <linkname>.").WithDefault("<dst>"),
|
||||
cmdkit.BoolOption(refsEdgesOptionName, "e", "Emit edge format: `<from> -> <to>`."),
|
||||
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
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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)),
|
||||
}
|
||||
|
||||
@ -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 <command> --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
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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 = "<no protocol name>"
|
||||
}
|
||||
|
||||
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{},
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
66
core/core.go
66
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"
|
||||
|
||||
@ -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"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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")
|
||||
)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
58
core/coreapi/interface/options/pubsub.go
Normal file
58
core/coreapi/interface/options/pubsub.go
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
304
core/coreapi/interface/options/unixfs.go
Normal file
304
core/coreapi/interface/options/unixfs.go
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
)
|
||||
|
||||
48
core/coreapi/interface/pubsub.go
Normal file
48
core/coreapi/interface/pubsub.go
Normal file
@ -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)
|
||||
}
|
||||
57
core/coreapi/interface/swarm.go
Normal file
57
core/coreapi/interface/swarm.go
Normal file
@ -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)
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
165
core/coreapi/pubsub.go
Normal file
165
core/coreapi/pubsub.go
Normal file
@ -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)
|
||||
}
|
||||
96
core/coreapi/pubsub_test.go
Normal file
96
core/coreapi/pubsub_test.go
Normal file
@ -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))
|
||||
}
|
||||
}
|
||||
175
core/coreapi/swarm.go
Normal file
175
core/coreapi/swarm.go
Normal file
@ -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
|
||||
}
|
||||
190
core/coreapi/unixfile.go
Normal file
190
core/coreapi/unixfile.go
Normal file
@ -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{}
|
||||
@ -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`.
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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 (<cid> or
|
||||
// /ipfs/<cid>) 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
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user