Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
go-ipfs
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
jihao
go-ipfs
Commits
7b09b7bd
提交
7b09b7bd
authored
11月 19, 2014
作者:
Matt Bell
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #364 from jbenet/pin-ls
Added 'pin ls' Command
上级
91fe0d95
5461d769
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
180 行增加
和
63 行删除
+180
-63
helptext.go
commands/cli/helptext.go
+3
-3
parse.go
commands/cli/parse.go
+10
-3
parse_test.go
commands/cli/parse_test.go
+1
-1
command.go
commands/command.go
+2
-2
command_test.go
commands/command_test.go
+5
-5
option.go
commands/option.go
+36
-13
request.go
commands/request.go
+10
-17
add.go
core/commands/add.go
+3
-0
pin.go
core/commands/pin.go
+64
-0
refs.go
core/commands/refs.go
+24
-19
indirect.go
pin/indirect.go
+4
-0
pin.go
pin/pin.go
+18
-0
没有找到文件。
commands/cli/helptext.go
浏览文件 @
7b09b7bd
...
...
@@ -239,7 +239,7 @@ func optionText(cmd ...*cmds.Command) []string {
lines
=
append
(
lines
,
""
)
}
names
:=
sortByLength
(
opt
.
Names
)
names
:=
sortByLength
(
opt
.
Names
()
)
if
len
(
names
)
>=
j
+
1
{
lines
[
i
]
+=
fmt
.
Sprintf
(
optionFlag
,
names
[
j
])
}
...
...
@@ -262,13 +262,13 @@ func optionText(cmd ...*cmds.Command) []string {
// add option types to output
for
i
,
opt
:=
range
options
{
lines
[
i
]
+=
" "
+
fmt
.
Sprintf
(
"%v"
,
opt
.
Type
)
lines
[
i
]
+=
" "
+
fmt
.
Sprintf
(
"%v"
,
opt
.
Type
()
)
}
lines
=
align
(
lines
)
// add option descriptions to output
for
i
,
opt
:=
range
options
{
lines
[
i
]
+=
" - "
+
opt
.
Description
lines
[
i
]
+=
" - "
+
opt
.
Description
()
}
return
lines
...
...
commands/cli/parse.go
浏览文件 @
7b09b7bd
...
...
@@ -46,10 +46,17 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
return
nil
,
cmd
,
path
,
err
}
recursive
,
_
,
err
:=
req
.
Option
(
cmds
.
RecShort
)
.
Bool
()
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
u
.
ErrCast
()
// if -r is provided, and it is associated with the package builtin
// recursive path option, allow recursive file paths
recursiveOpt
:=
req
.
Option
(
cmds
.
RecShort
)
recursive
:=
false
if
recursiveOpt
!=
nil
&&
recursiveOpt
.
Definition
()
==
cmds
.
OptionRecursivePath
{
recursive
,
_
,
err
=
recursiveOpt
.
Bool
()
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
u
.
ErrCast
()
}
}
stringArgs
,
fileArgs
,
err
:=
parseArgs
(
stringVals
,
stdin
,
cmd
.
Arguments
,
recursive
)
if
err
!=
nil
{
return
nil
,
cmd
,
path
,
err
...
...
commands/cli/parse_test.go
浏览文件 @
7b09b7bd
...
...
@@ -11,7 +11,7 @@ func TestOptionParsing(t *testing.T) {
subCmd
:=
&
commands
.
Command
{}
cmd
:=
&
commands
.
Command
{
Options
:
[]
commands
.
Option
{
commands
.
Option
{
Names
:
[]
string
{
"b"
},
Type
:
commands
.
String
}
,
commands
.
StringOption
(
"b"
,
"some option"
)
,
},
Subcommands
:
map
[
string
]
*
commands
.
Command
{
"test"
:
subCmd
,
...
...
commands/command.go
浏览文件 @
7b09b7bd
...
...
@@ -167,7 +167,7 @@ func (c *Command) Get(path []string) (*Command, error) {
// GetOptions gets the options in the given path of commands
func
(
c
*
Command
)
GetOptions
(
path
[]
string
)
(
map
[
string
]
Option
,
error
)
{
options
:=
make
([]
Option
,
len
(
c
.
Options
))
options
:=
make
([]
Option
,
0
,
len
(
c
.
Options
))
cmds
,
err
:=
c
.
Resolve
(
path
)
if
err
!=
nil
{
...
...
@@ -181,7 +181,7 @@ func (c *Command) GetOptions(path []string) (map[string]Option, error) {
optionsMap
:=
make
(
map
[
string
]
Option
)
for
_
,
opt
:=
range
options
{
for
_
,
name
:=
range
opt
.
Names
{
for
_
,
name
:=
range
opt
.
Names
()
{
if
_
,
found
:=
optionsMap
[
name
];
found
{
return
nil
,
fmt
.
Errorf
(
"Option name '%s' used multiple times"
,
name
)
}
...
...
commands/command_test.go
浏览文件 @
7b09b7bd
...
...
@@ -9,8 +9,8 @@ func noop(req Request) (interface{}, error) {
func
TestOptionValidation
(
t
*
testing
.
T
)
{
cmd
:=
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"b"
,
"beep"
},
Int
,
"enables beeper"
}
,
Option
{[]
string
{
"B"
,
"boop"
},
String
,
"password for booper"
}
,
IntOption
(
"b"
,
"beep"
,
"enables beeper"
)
,
StringOption
(
"B"
,
"boop"
,
"password for booper"
)
,
},
Run
:
noop
,
}
...
...
@@ -93,14 +93,14 @@ func TestOptionValidation(t *testing.T) {
func
TestRegistration
(
t
*
testing
.
T
)
{
cmdA
:=
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"beep"
},
Int
,
"number of beeps"
}
,
IntOption
(
"beep"
,
"number of beeps"
)
,
},
Run
:
noop
,
}
cmdB
:=
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"beep"
},
Int
,
"number of beeps"
}
,
IntOption
(
"beep"
,
"number of beeps"
)
,
},
Run
:
noop
,
Subcommands
:
map
[
string
]
*
Command
{
...
...
@@ -110,7 +110,7 @@ func TestRegistration(t *testing.T) {
cmdC
:=
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"encoding"
},
String
,
"data encoding type"
}
,
StringOption
(
"encoding"
,
"data encoding type"
)
,
},
Run
:
noop
,
}
...
...
commands/option.go
浏览文件 @
7b09b7bd
...
...
@@ -17,14 +17,28 @@ const (
)
// Option is used to specify a field that will be provided by a consumer
type
Option
struct
{
Names
[]
string
// a list of unique names to
Type
reflect
.
Kind
// value must be this type
Description
string
// a short string to describe this option
type
Option
interface
{
Names
()
[]
string
// a list of unique names matched with user-provided flags
Type
()
reflect
.
Kind
// value must be this type
Description
()
string
// a short string that describes this option
}
type
option
struct
{
names
[]
string
kind
reflect
.
Kind
description
string
}
func
(
o
*
option
)
Names
()
[]
string
{
return
o
.
names
}
// MAYBE_TODO: add more features(?):
//Default interface{} // the default value (ignored if `Required` is true)
//Required bool // whether or not the option must be provided
func
(
o
*
option
)
Type
()
reflect
.
Kind
{
return
o
.
kind
}
func
(
o
*
option
)
Description
()
string
{
return
o
.
description
}
// constructor helper functions
...
...
@@ -37,10 +51,10 @@ func NewOption(kind reflect.Kind, names ...string) Option {
desc
:=
names
[
len
(
names
)
-
1
]
names
=
names
[
:
len
(
names
)
-
1
]
return
O
ption
{
N
ames
:
names
,
Type
:
kind
,
D
escription
:
desc
,
return
&
o
ption
{
n
ames
:
names
,
kind
:
kind
,
d
escription
:
desc
,
}
}
...
...
@@ -69,6 +83,7 @@ func StringOption(names ...string) Option {
type
OptionValue
struct
{
value
interface
{}
found
bool
def
Option
}
// Found returns true if the option value was provided by the user (not a default value)
...
...
@@ -76,6 +91,11 @@ func (ov OptionValue) Found() bool {
return
ov
.
found
}
// Definition returns the option definition for the provided value
func
(
ov
OptionValue
)
Definition
()
Option
{
return
ov
.
def
}
// value accessor methods, gets the value as a certain type
func
(
ov
OptionValue
)
Bool
()
(
value
bool
,
found
bool
,
err
error
)
{
if
!
ov
.
found
{
...
...
@@ -141,9 +161,12 @@ const (
)
// options that are used by this package
var
OptionEncodingType
=
StringOption
(
EncShort
,
EncLong
,
"The encoding type the output should be encoded with (json, xml, or text)"
)
var
OptionRecursivePath
=
BoolOption
(
RecShort
,
RecLong
,
"Add directory paths recursively"
)
// global options, added to every command
var
globalOptions
=
[]
Option
{
StringOption
(
EncShort
,
EncLong
,
"The encoding type the output should be encoded with (json, xml, or text)"
),
BoolOption
(
RecShort
,
RecLong
,
"Add directory paths recursively"
),
OptionEncodingType
,
}
// the above array of Options, wrapped in a Command
...
...
commands/request.go
浏览文件 @
7b09b7bd
...
...
@@ -92,13 +92,6 @@ func (r *request) Path() []string {
// Option returns the value of the option for given name.
func
(
r
*
request
)
Option
(
name
string
)
*
OptionValue
{
val
,
found
:=
r
.
options
[
name
]
if
found
{
return
&
OptionValue
{
val
,
found
}
}
// if a value isn't defined for that name, we will try to look it up by its aliases
// find the option with the specified name
option
,
found
:=
r
.
optionDefs
[
name
]
if
!
found
{
...
...
@@ -106,15 +99,15 @@ func (r *request) Option(name string) *OptionValue {
}
// try all the possible names, break if we find a value
for
_
,
n
:=
range
option
.
Names
{
val
,
found
=
r
.
options
[
n
]
for
_
,
n
:=
range
option
.
Names
()
{
val
,
found
:
=
r
.
options
[
n
]
if
found
{
return
&
OptionValue
{
val
,
found
}
return
&
OptionValue
{
val
,
found
,
option
}
}
}
// MAYBE_TODO: use default value instead of nil
return
&
OptionValue
{
nil
,
false
}
return
&
OptionValue
{
nil
,
false
,
option
}
}
// Options returns a copy of the option map
...
...
@@ -135,7 +128,7 @@ func (r *request) SetOption(name string, val interface{}) {
}
// try all the possible names, if we already have a value then set over it
for
_
,
n
:=
range
option
.
Names
{
for
_
,
n
:=
range
option
.
Names
()
{
_
,
found
:=
r
.
options
[
n
]
if
found
{
r
.
options
[
n
]
=
val
...
...
@@ -222,9 +215,9 @@ func (r *request) ConvertOptions() error {
}
kind
:=
reflect
.
TypeOf
(
v
)
.
Kind
()
if
kind
!=
opt
.
Type
{
if
kind
!=
opt
.
Type
()
{
if
kind
==
String
{
convert
:=
converters
[
opt
.
Type
]
convert
:=
converters
[
opt
.
Type
()
]
str
,
ok
:=
v
.
(
string
)
if
!
ok
{
return
u
.
ErrCast
()
...
...
@@ -236,19 +229,19 @@ func (r *request) ConvertOptions() error {
value
=
"empty value"
}
return
fmt
.
Errorf
(
"Could not convert %s to type '%s' (for option '-%s')"
,
value
,
opt
.
Type
.
String
(),
k
)
value
,
opt
.
Type
()
.
String
(),
k
)
}
r
.
options
[
k
]
=
val
}
else
{
return
fmt
.
Errorf
(
"Option '%s' should be type '%s', but got type '%s'"
,
k
,
opt
.
Type
.
String
(),
kind
.
String
())
k
,
opt
.
Type
()
.
String
(),
kind
.
String
())
}
}
else
{
r
.
options
[
k
]
=
v
}
for
_
,
name
:=
range
opt
.
Names
{
for
_
,
name
:=
range
opt
.
Names
()
{
if
_
,
ok
:=
r
.
options
[
name
];
name
!=
k
&&
ok
{
return
fmt
.
Errorf
(
"Duplicate command options were provided ('%s' and '%s')"
,
k
,
name
)
...
...
core/commands/add.go
浏览文件 @
7b09b7bd
...
...
@@ -39,6 +39,9 @@ remains to be implemented.
Arguments
:
[]
cmds
.
Argument
{
cmds
.
FileArg
(
"path"
,
true
,
true
,
"The path to a file to be added to IPFS"
)
.
EnableRecursive
(),
},
Options
:
[]
cmds
.
Option
{
cmds
.
OptionRecursivePath
,
// a builtin option that allows recursive paths (-r, --recursive)
},
Run
:
func
(
req
cmds
.
Request
)
(
interface
{},
error
)
{
added
:=
&
AddOutput
{}
n
,
err
:=
req
.
Context
()
.
GetNode
()
...
...
core/commands/pin.go
浏览文件 @
7b09b7bd
...
...
@@ -6,6 +6,7 @@ import (
cmds
"github.com/jbenet/go-ipfs/commands"
"github.com/jbenet/go-ipfs/core"
"github.com/jbenet/go-ipfs/merkledag"
u
"github.com/jbenet/go-ipfs/util"
)
var
pinCmd
=
&
cmds
.
Command
{
...
...
@@ -16,6 +17,7 @@ var pinCmd = &cmds.Command{
Subcommands
:
map
[
string
]
*
cmds
.
Command
{
"add"
:
addPinCmd
,
"rm"
:
rmPinCmd
,
"ls"
:
listPinCmd
,
},
}
...
...
@@ -99,6 +101,68 @@ collected if needed.
},
}
var
listPinCmd
=
&
cmds
.
Command
{
Helptext
:
cmds
.
HelpText
{
Tagline
:
"List objects pinned to local storage"
,
ShortDescription
:
`
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.
`
,
LongDescription
:
`
Returns a list of hashes of objects being pinned. Objects that are indirectly
or recursively pinned are not included in the list.
Use --type=<type> to specify the type of pinned keys to list. Valid values are:
* "direct"
* "indirect"
* "recursive"
* "all"
(Defaults to "direct")
`
,
},
Options
:
[]
cmds
.
Option
{
cmds
.
StringOption
(
"type"
,
"t"
,
"The type of pinned keys to list. Can be
\"
direct
\"
,
\"
indirect
\"
,
\"
recursive
\"
, or
\"
all
\"
. Defaults to
\"
direct
\"
"
),
},
Run
:
func
(
req
cmds
.
Request
)
(
interface
{},
error
)
{
n
,
err
:=
req
.
Context
()
.
GetNode
()
if
err
!=
nil
{
return
nil
,
err
}
typeStr
,
found
,
err
:=
req
.
Option
(
"type"
)
.
String
()
if
err
!=
nil
{
return
nil
,
err
}
if
!
found
{
typeStr
=
"direct"
}
switch
typeStr
{
case
"all"
,
"direct"
,
"indirect"
,
"recursive"
:
default
:
return
nil
,
cmds
.
ClientError
(
"Invalid type '"
+
typeStr
+
"', must be one of {direct, indirect, recursive, all}"
)
}
keys
:=
make
([]
u
.
Key
,
0
)
if
typeStr
==
"direct"
||
typeStr
==
"all"
{
keys
=
append
(
keys
,
n
.
Pinning
.
DirectKeys
()
...
)
}
if
typeStr
==
"indirect"
||
typeStr
==
"all"
{
keys
=
append
(
keys
,
n
.
Pinning
.
IndirectKeys
()
...
)
}
if
typeStr
==
"recursive"
||
typeStr
==
"all"
{
keys
=
append
(
keys
,
n
.
Pinning
.
RecursiveKeys
()
...
)
}
return
&
KeyList
{
Keys
:
keys
},
nil
},
Type
:
&
KeyList
{},
Marshalers
:
cmds
.
MarshalerMap
{
cmds
.
Text
:
KeyListTextMarshaler
,
},
}
func
pin
(
n
*
core
.
IpfsNode
,
paths
[]
string
,
recursive
bool
)
([]
*
merkledag
.
Node
,
error
)
{
dagnodes
:=
make
([]
*
merkledag
.
Node
,
0
)
...
...
core/commands/refs.go
浏览文件 @
7b09b7bd
...
...
@@ -10,8 +10,19 @@ import (
u
"github.com/jbenet/go-ipfs/util"
)
type
RefsOutput
struct
{
Refs
[]
string
// KeyList is a general type for outputting lists of keys
type
KeyList
struct
{
Keys
[]
u
.
Key
}
// KeyListTextMarshaler outputs a KeyList as plaintext, one key per line
func
KeyListTextMarshaler
(
res
cmds
.
Response
)
([]
byte
,
error
)
{
output
:=
res
.
Output
()
.
(
*
KeyList
)
s
:=
""
for
_
,
key
:=
range
output
.
Keys
{
s
+=
key
.
B58String
()
+
"
\n
"
}
return
[]
byte
(
s
),
nil
}
var
refsCmd
=
&
cmds
.
Command
{
...
...
@@ -58,26 +69,19 @@ Note: list all refs recursively with -r.
return
getRefs
(
n
,
req
.
Arguments
(),
unique
,
recursive
)
},
Type
:
&
RefsOutpu
t
{},
Type
:
&
KeyLis
t
{},
Marshalers
:
cmds
.
MarshalerMap
{
cmds
.
Text
:
func
(
res
cmds
.
Response
)
([]
byte
,
error
)
{
output
:=
res
.
Output
()
.
(
*
RefsOutput
)
s
:=
""
for
_
,
ref
:=
range
output
.
Refs
{
s
+=
fmt
.
Sprintln
(
ref
)
}
return
[]
byte
(
s
),
nil
},
cmds
.
Text
:
KeyListTextMarshaler
,
},
}
func
getRefs
(
n
*
core
.
IpfsNode
,
paths
[]
string
,
unique
,
recursive
bool
)
(
*
RefsOutpu
t
,
error
)
{
func
getRefs
(
n
*
core
.
IpfsNode
,
paths
[]
string
,
unique
,
recursive
bool
)
(
*
KeyLis
t
,
error
)
{
var
refsSeen
map
[
u
.
Key
]
bool
if
unique
{
refsSeen
=
make
(
map
[
u
.
Key
]
bool
)
}
refs
:=
make
([]
string
,
0
)
refs
:=
make
([]
u
.
Key
,
0
)
for
_
,
path
:=
range
paths
{
object
,
err
:=
n
.
Resolver
.
ResolvePath
(
path
)
...
...
@@ -91,10 +95,10 @@ func getRefs(n *core.IpfsNode, paths []string, unique, recursive bool) (*RefsOut
}
}
return
&
RefsOutpu
t
{
refs
},
nil
return
&
KeyLis
t
{
refs
},
nil
}
func
addRefs
(
n
*
core
.
IpfsNode
,
object
*
dag
.
Node
,
refs
[]
string
,
refsSeen
map
[
u
.
Key
]
bool
,
recursive
bool
)
([]
string
,
error
)
{
func
addRefs
(
n
*
core
.
IpfsNode
,
object
*
dag
.
Node
,
refs
[]
u
.
Key
,
refsSeen
map
[
u
.
Key
]
bool
,
recursive
bool
)
([]
u
.
Key
,
error
)
{
for
_
,
link
:=
range
object
.
Links
{
var
found
bool
found
,
refs
=
addRef
(
link
.
Hash
,
refs
,
refsSeen
)
...
...
@@ -115,15 +119,16 @@ func addRefs(n *core.IpfsNode, object *dag.Node, refs []string, refsSeen map[u.K
return
refs
,
nil
}
func
addRef
(
h
mh
.
Multihash
,
refs
[]
string
,
refsSeen
map
[
u
.
Key
]
bool
)
(
bool
,
[]
string
)
{
func
addRef
(
h
mh
.
Multihash
,
refs
[]
u
.
Key
,
refsSeen
map
[
u
.
Key
]
bool
)
(
bool
,
[]
u
.
Key
)
{
key
:=
u
.
Key
(
h
)
if
refsSeen
!=
nil
{
_
,
found
:=
refsSeen
[
u
.
Key
(
h
)
]
_
,
found
:=
refsSeen
[
key
]
if
found
{
return
true
,
refs
}
refsSeen
[
u
.
Key
(
h
)
]
=
true
refsSeen
[
key
]
=
true
}
refs
=
append
(
refs
,
h
.
B58String
()
)
refs
=
append
(
refs
,
key
)
return
false
,
refs
}
pin/indirect.go
浏览文件 @
7b09b7bd
...
...
@@ -65,3 +65,7 @@ func (i *indirectPin) Decrement(k util.Key) {
func
(
i
*
indirectPin
)
HasKey
(
k
util
.
Key
)
bool
{
return
i
.
blockset
.
HasKey
(
k
)
}
func
(
i
*
indirectPin
)
Set
()
set
.
BlockSet
{
return
i
.
blockset
}
pin/pin.go
浏览文件 @
7b09b7bd
...
...
@@ -33,6 +33,9 @@ type Pinner interface {
Unpin
(
util
.
Key
,
bool
)
error
Flush
()
error
GetManual
()
ManualPinner
DirectKeys
()
[]
util
.
Key
IndirectKeys
()
[]
util
.
Key
RecursiveKeys
()
[]
util
.
Key
}
// ManualPinner is for manually editing the pin structure
...
...
@@ -207,6 +210,21 @@ func LoadPinner(d ds.Datastore, dserv mdag.DAGService) (Pinner, error) {
return
p
,
nil
}
// DirectKeys returns a slice containing the directly pinned keys
func
(
p
*
pinner
)
DirectKeys
()
[]
util
.
Key
{
return
p
.
directPin
.
GetKeys
()
}
// IndirectKeys returns a slice containing the indirectly pinned keys
func
(
p
*
pinner
)
IndirectKeys
()
[]
util
.
Key
{
return
p
.
indirPin
.
Set
()
.
GetKeys
()
}
// RecursiveKeys returns a slice containing the recursively pinned keys
func
(
p
*
pinner
)
RecursiveKeys
()
[]
util
.
Key
{
return
p
.
recursePin
.
GetKeys
()
}
// Flush encodes and writes pinner keysets to the datastore
func
(
p
*
pinner
)
Flush
()
error
{
p
.
lock
.
RLock
()
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论