Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
G
go-ipfs
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
jihao
go-ipfs
Commits
10048cec
提交
10048cec
authored
8月 18, 2016
作者:
Jeromy Johnson
提交者:
GitHub
8月 18, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #2962 from ipfs/kevina/block-rm
Add "ipfs block rm" command.
上级
6bb8a1f9
8679af7a
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
347 行增加
和
3 行删除
+347
-3
arc_cache.go
blocks/blockstore/arc_cache.go
+1
-1
block.go
core/commands/block.go
+136
-0
pin.go
pin/pin.go
+74
-0
t0050-block.sh
test/sharness/t0050-block.sh
+136
-2
没有找到文件。
blocks/blockstore/arc_cache.go
浏览文件 @
10048cec
...
...
@@ -32,7 +32,7 @@ func (b *arccache) DeleteBlock(k key.Key) error {
switch
err
{
case
nil
,
ds
.
ErrNotFound
,
ErrNotFound
:
b
.
arc
.
Add
(
k
,
false
)
return
nil
return
err
default
:
return
err
}
...
...
core/commands/block.go
浏览文件 @
10048cec
...
...
@@ -9,8 +9,11 @@ import (
"strings"
"github.com/ipfs/go-ipfs/blocks"
bs
"github.com/ipfs/go-ipfs/blocks/blockstore"
key
"github.com/ipfs/go-ipfs/blocks/key"
cmds
"github.com/ipfs/go-ipfs/commands"
"github.com/ipfs/go-ipfs/pin"
ds
"gx/ipfs/QmTxLSvdhwg68WJimdS6icLPhZi28aTp6b7uihC2Yb47Xk/go-datastore"
mh
"gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
u
"gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
)
...
...
@@ -38,6 +41,7 @@ multihash.
"stat"
:
blockStatCmd
,
"get"
:
blockGetCmd
,
"put"
:
blockPutCmd
,
"rm"
:
blockRmCmd
,
},
}
...
...
@@ -185,3 +189,135 @@ func getBlockForKey(req cmds.Request, skey string) (blocks.Block, error) {
log
.
Debugf
(
"ipfs block: got block with key: %q"
,
b
.
Key
())
return
b
,
nil
}
var
blockRmCmd
=
&
cmds
.
Command
{
Helptext
:
cmds
.
HelpText
{
Tagline
:
"Remove IPFS block(s)."
,
ShortDescription
:
`
'ipfs block rm' is a plumbing command for removing raw ipfs blocks.
It takes a list of base58 encoded multihashs to remove.
`
,
},
Arguments
:
[]
cmds
.
Argument
{
cmds
.
StringArg
(
"hash"
,
true
,
true
,
"Bash58 encoded multihash of block(s) to remove."
),
},
Options
:
[]
cmds
.
Option
{
cmds
.
BoolOption
(
"force"
,
"f"
,
"Ignore nonexistent blocks."
)
.
Default
(
false
),
cmds
.
BoolOption
(
"quiet"
,
"q"
,
"Write minimal output."
)
.
Default
(
false
),
},
Run
:
func
(
req
cmds
.
Request
,
res
cmds
.
Response
)
{
n
,
err
:=
req
.
InvocContext
()
.
GetNode
()
if
err
!=
nil
{
res
.
SetError
(
err
,
cmds
.
ErrNormal
)
return
}
hashes
:=
req
.
Arguments
()
force
,
_
,
_
:=
req
.
Option
(
"force"
)
.
Bool
()
quiet
,
_
,
_
:=
req
.
Option
(
"quiet"
)
.
Bool
()
keys
:=
make
([]
key
.
Key
,
0
,
len
(
hashes
))
for
_
,
hash
:=
range
hashes
{
k
:=
key
.
B58KeyDecode
(
hash
)
keys
=
append
(
keys
,
k
)
}
outChan
:=
make
(
chan
interface
{})
res
.
SetOutput
((
<-
chan
interface
{})(
outChan
))
go
func
()
{
defer
close
(
outChan
)
pinning
:=
n
.
Pinning
err
:=
rmBlocks
(
n
.
Blockstore
,
pinning
,
outChan
,
keys
,
rmBlocksOpts
{
quiet
:
quiet
,
force
:
force
,
})
if
err
!=
nil
{
outChan
<-
&
RemovedBlock
{
Error
:
err
.
Error
()}
}
}()
return
},
PostRun
:
func
(
req
cmds
.
Request
,
res
cmds
.
Response
)
{
if
res
.
Error
()
!=
nil
{
return
}
outChan
,
ok
:=
res
.
Output
()
.
(
<-
chan
interface
{})
if
!
ok
{
res
.
SetError
(
u
.
ErrCast
(),
cmds
.
ErrNormal
)
return
}
res
.
SetOutput
(
nil
)
someFailed
:=
false
for
out
:=
range
outChan
{
o
:=
out
.
(
*
RemovedBlock
)
if
o
.
Hash
==
""
&&
o
.
Error
!=
""
{
res
.
SetError
(
fmt
.
Errorf
(
"aborted: %s"
,
o
.
Error
),
cmds
.
ErrNormal
)
return
}
else
if
o
.
Error
!=
""
{
someFailed
=
true
fmt
.
Fprintf
(
res
.
Stderr
(),
"cannot remove %s: %s
\n
"
,
o
.
Hash
,
o
.
Error
)
}
else
{
fmt
.
Fprintf
(
res
.
Stdout
(),
"removed %s
\n
"
,
o
.
Hash
)
}
}
if
someFailed
{
res
.
SetError
(
fmt
.
Errorf
(
"some blocks not removed"
),
cmds
.
ErrNormal
)
}
},
Type
:
RemovedBlock
{},
}
type
RemovedBlock
struct
{
Hash
string
`json:",omitempty"`
Error
string
`json:",omitempty"`
}
type
rmBlocksOpts
struct
{
quiet
bool
force
bool
}
func
rmBlocks
(
blocks
bs
.
GCBlockstore
,
pins
pin
.
Pinner
,
out
chan
<-
interface
{},
keys
[]
key
.
Key
,
opts
rmBlocksOpts
)
error
{
unlocker
:=
blocks
.
GCLock
()
defer
unlocker
.
Unlock
()
stillOkay
,
err
:=
checkIfPinned
(
pins
,
keys
,
out
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"pin check failed: %s"
,
err
)
}
for
_
,
k
:=
range
stillOkay
{
err
:=
blocks
.
DeleteBlock
(
k
)
if
err
!=
nil
&&
opts
.
force
&&
(
err
==
bs
.
ErrNotFound
||
err
==
ds
.
ErrNotFound
)
{
// ignore non-existent blocks
}
else
if
err
!=
nil
{
out
<-
&
RemovedBlock
{
Hash
:
k
.
String
(),
Error
:
err
.
Error
()}
}
else
if
!
opts
.
quiet
{
out
<-
&
RemovedBlock
{
Hash
:
k
.
String
()}
}
}
return
nil
}
func
checkIfPinned
(
pins
pin
.
Pinner
,
keys
[]
key
.
Key
,
out
chan
<-
interface
{})
([]
key
.
Key
,
error
)
{
stillOkay
:=
make
([]
key
.
Key
,
0
,
len
(
keys
))
res
,
err
:=
pins
.
CheckIfPinned
(
keys
...
)
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
r
:=
range
res
{
switch
r
.
Mode
{
case
pin
.
NotPinned
:
stillOkay
=
append
(
stillOkay
,
r
.
Key
)
case
pin
.
Indirect
:
out
<-
&
RemovedBlock
{
Hash
:
r
.
Key
.
String
(),
Error
:
fmt
.
Sprintf
(
"pinned via %s"
,
r
.
Via
)}
default
:
modeStr
,
_
:=
pin
.
PinModeToString
(
r
.
Mode
)
out
<-
&
RemovedBlock
{
Hash
:
r
.
Key
.
String
(),
Error
:
fmt
.
Sprintf
(
"pinned: %s"
,
modeStr
)}
}
}
return
stillOkay
,
nil
}
pin/pin.go
浏览文件 @
10048cec
...
...
@@ -75,6 +75,10 @@ type Pinner interface {
Pin
(
context
.
Context
,
*
mdag
.
Node
,
bool
)
error
Unpin
(
context
.
Context
,
key
.
Key
,
bool
)
error
// Check if a set of keys are pinned, more efficient than
// calling IsPinned for each key
CheckIfPinned
(
keys
...
key
.
Key
)
([]
Pinned
,
error
)
// PinWithMode is for manually editing the pin structure. Use with
// care! If used improperly, garbage collection may not be
// successful.
...
...
@@ -90,6 +94,12 @@ type Pinner interface {
InternalPins
()
[]
key
.
Key
}
type
Pinned
struct
{
Key
key
.
Key
Mode
PinMode
Via
key
.
Key
}
// pinner implements the Pinner interface
type
pinner
struct
{
lock
sync
.
RWMutex
...
...
@@ -255,6 +265,70 @@ func (p *pinner) isPinnedWithType(k key.Key, mode PinMode) (string, bool, error)
return
""
,
false
,
nil
}
func
(
p
*
pinner
)
CheckIfPinned
(
keys
...
key
.
Key
)
([]
Pinned
,
error
)
{
p
.
lock
.
RLock
()
defer
p
.
lock
.
RUnlock
()
pinned
:=
make
([]
Pinned
,
0
,
len
(
keys
))
toCheck
:=
make
(
map
[
key
.
Key
]
struct
{})
// First check for non-Indirect pins directly
for
_
,
k
:=
range
keys
{
if
p
.
recursePin
.
HasKey
(
k
)
{
pinned
=
append
(
pinned
,
Pinned
{
Key
:
k
,
Mode
:
Recursive
})
}
else
if
p
.
directPin
.
HasKey
(
k
)
{
pinned
=
append
(
pinned
,
Pinned
{
Key
:
k
,
Mode
:
Direct
})
}
else
if
p
.
isInternalPin
(
k
)
{
pinned
=
append
(
pinned
,
Pinned
{
Key
:
k
,
Mode
:
Internal
})
}
else
{
toCheck
[
k
]
=
struct
{}{}
}
}
// Now walk all recursive pins to check for indirect pins
var
checkChildren
func
(
key
.
Key
,
key
.
Key
)
error
checkChildren
=
func
(
rk
key
.
Key
,
parentKey
key
.
Key
)
error
{
parent
,
err
:=
p
.
dserv
.
Get
(
context
.
Background
(),
parentKey
)
if
err
!=
nil
{
return
err
}
for
_
,
lnk
:=
range
parent
.
Links
{
k
:=
key
.
Key
(
lnk
.
Hash
)
if
_
,
found
:=
toCheck
[
k
];
found
{
pinned
=
append
(
pinned
,
Pinned
{
Key
:
k
,
Mode
:
Indirect
,
Via
:
rk
})
delete
(
toCheck
,
k
)
}
err
:=
checkChildren
(
rk
,
k
)
if
err
!=
nil
{
return
err
}
if
len
(
toCheck
)
==
0
{
return
nil
}
}
return
nil
}
for
_
,
rk
:=
range
p
.
recursePin
.
GetKeys
()
{
err
:=
checkChildren
(
rk
,
rk
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
toCheck
)
==
0
{
break
}
}
// Anything left in toCheck is not pinned
for
k
,
_
:=
range
toCheck
{
pinned
=
append
(
pinned
,
Pinned
{
Key
:
k
,
Mode
:
NotPinned
})
}
return
pinned
,
nil
}
func
(
p
*
pinner
)
RemovePinWithMode
(
key
key
.
Key
,
mode
PinMode
)
{
p
.
lock
.
Lock
()
defer
p
.
lock
.
Unlock
()
...
...
test/sharness/t0050-block.sh
浏览文件 @
10048cec
...
...
@@ -10,17 +10,26 @@ test_description="Test block command"
test_init_ipfs
HASH
=
"QmRKqGMAM6EZngbpjSqrvYzq5Qd8b1bSWymjSUY9zQSNDk"
#
# "block put tests"
#
test_expect_success
"'ipfs block put' succeeds"
'
echo "Hello Mars!" >expected_in &&
ipfs block put <expected_in >actual_out
'
test_expect_success
"'ipfs block put' output looks good"
'
HASH="QmRKqGMAM6EZngbpjSqrvYzq5Qd8b1bSWymjSUY9zQSNDk" &&
echo "$HASH" >expected_out &&
test_cmp expected_out actual_out
'
#
# "block get" tests
#
test_expect_success
"'ipfs block get' succeeds"
'
ipfs block get $HASH >actual_in
'
...
...
@@ -29,16 +38,141 @@ test_expect_success "'ipfs block get' output looks good" '
test_cmp expected_in actual_in
'
#
# "block stat" tests
#
test_expect_success
"'ipfs block stat' succeeds"
'
ipfs block stat $HASH >actual_stat
'
test_expect_success
"'ipfs block
ge
t' output looks good"
'
test_expect_success
"'ipfs block
sta
t' output looks good"
'
echo "Key: $HASH" >expected_stat &&
echo "Size: 12" >>expected_stat &&
test_cmp expected_stat actual_stat
'
#
# "block rm" tests
#
test_expect_success
"'ipfs block rm' succeeds"
'
ipfs block rm $HASH >actual_rm
'
test_expect_success
"'ipfs block rm' output looks good"
'
echo "removed $HASH" > expected_rm &&
test_cmp expected_rm actual_rm
'
test_expect_success
"'ipfs block rm' block actually removed"
'
test_must_fail ipfs block stat $HASH
'
DIRHASH
=
QmdWmVmM6W2abTgkEfpbtA1CJyTWS2rhuUB9uP1xV8Uwtf
FILE1HASH
=
Qmae3RedM7SNkWGsdzYzsr6svmsFdsva4WoTvYYsWhUSVz
FILE2HASH
=
QmUtkGLvPf63NwVzLPKPUYgwhn8ZYPWF6vKWN3fZ2amfJF
FILE3HASH
=
Qmesmmf1EEG1orJb6XdK6DabxexsseJnCfw8pqWgonbkoj
test_expect_success
"add and pin directory"
'
mkdir adir &&
echo "file1" > adir/file1 &&
echo "file2" > adir/file2 &&
echo "file3" > adir/file3 &&
ipfs add -r adir
ipfs pin add -r $DIRHASH
'
test_expect_success
"can't remove pinned block"
'
test_must_fail ipfs block rm $DIRHASH 2> block_rm_err
'
test_expect_success
"can't remove pinned block: output looks good"
'
grep -q "$DIRHASH: pinned: recursive" block_rm_err
'
test_expect_success
"can't remove indirectly pinned block"
'
test_must_fail ipfs block rm $FILE1HASH 2> block_rm_err
'
test_expect_success
"can't remove indirectly pinned block: output looks good"
'
grep -q "$FILE1HASH: pinned via $DIRHASH" block_rm_err
'
test_expect_success
"remove pin"
'
ipfs pin rm -r $DIRHASH
'
test_expect_success
"multi-block 'ipfs block rm' succeeds"
'
ipfs block rm $FILE1HASH $FILE2HASH $FILE3HASH > actual_rm
'
test_expect_success
"multi-block 'ipfs block rm' output looks good"
'
grep -F -q "removed $FILE1HASH" actual_rm &&
grep -F -q "removed $FILE2HASH" actual_rm &&
grep -F -q "removed $FILE3HASH" actual_rm
'
test_expect_success
"'add some blocks' succeeds"
'
echo "Hello Mars!" | ipfs block put &&
echo "Hello Venus!" | ipfs block put
'
test_expect_success
"add and pin directory"
'
ipfs add -r adir
ipfs pin add -r $DIRHASH
'
HASH
=
QmRKqGMAM6EZngbpjSqrvYzq5Qd8b1bSWymjSUY9zQSNDk
HASH2
=
QmdnpnsaEj69isdw5sNzp3h3HkaDz7xKq7BmvFFBzNr5e7
RANDOMHASH
=
QRmKqGMAM6EbngbZjSqrvYzq5Qd8b1bSWymjSUY9zQSNDq
test_expect_success
"multi-block 'ipfs block rm' mixed"
'
test_must_fail ipfs block rm $FILE1HASH $DIRHASH $HASH $FILE3HASH $RANDOMHASH $HASH2 2> block_rm_err
'
test_expect_success
"pinned block not removed"
'
ipfs block stat $FILE1HASH &&
ipfs block stat $FILE3HASH
'
test_expect_success
"non-pinned blocks removed"
'
test_must_fail ipfs block stat $HASH &&
test_must_fail ipfs block stat $HASH2
'
test_expect_success
"error reported on removing non-existent block"
'
grep -q "cannot remove $RANDOMHASH" block_rm_err
'
test_expect_success
"'add some blocks' succeeds"
'
echo "Hello Mars!" | ipfs block put &&
echo "Hello Venus!" | ipfs block put
'
test_expect_success
"multi-block 'ipfs block rm -f' with non existent blocks succeed"
'
ipfs block rm -f $HASH $RANDOMHASH $HASH2
'
test_expect_success
"existent blocks removed"
'
test_must_fail ipfs block stat $HASH &&
test_must_fail ipfs block stat $HASH2
'
test_expect_success
"'add some blocks' succeeds"
'
echo "Hello Mars!" | ipfs block put &&
echo "Hello Venus!" | ipfs block put
'
test_expect_success
"multi-block 'ipfs block rm -q' produces no output"
'
ipfs block rm -q $HASH $HASH2 > block_rm_out &&
test ! -s block_rm_out
'
#
# Misc tests
#
test_expect_success
"'ipfs block stat' with nothing from stdin doesnt crash"
'
test_expect_code 1 ipfs block stat < /dev/null 2> stat_out
'
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论