Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-dms3
Commits
f46120b1
Commit
f46120b1
authored
Jan 07, 2015
by
Juan Batiz-Benet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refs edges + stream fix
parent
cb108f48
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
159 additions
and
50 deletions
+159
-50
core/commands/refs.go
core/commands/refs.go
+159
-50
No files found.
core/commands/refs.go
View file @
f46120b1
...
...
@@ -2,10 +2,11 @@ package commands
import
(
"bytes"
"fmt"
"io"
"sync"
context
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
mh
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
cmds
"github.com/jbenet/go-ipfs/commands"
"github.com/jbenet/go-ipfs/core"
dag
"github.com/jbenet/go-ipfs/merkledag"
...
...
@@ -44,6 +45,7 @@ Note: list all refs recursively with -r.
cmds
.
StringArg
(
"ipfs-path"
,
true
,
true
,
"Path to the object(s) to list refs from"
),
},
Options
:
[]
cmds
.
Option
{
cmds
.
BoolOption
(
"edges"
,
"e"
,
"Emit edge format: <from> -> <to>"
),
cmds
.
BoolOption
(
"unique"
,
"u"
,
"Omit duplicate refs from output"
),
cmds
.
BoolOption
(
"recursive"
,
"r"
,
"Recursively list links of child nodes"
),
},
...
...
@@ -53,84 +55,191 @@ Note: list all refs recursively with -r.
return
nil
,
err
}
unique
,
found
,
err
:=
req
.
Option
(
"unique"
)
.
Bool
()
unique
,
_
,
err
:=
req
.
Option
(
"unique"
)
.
Bool
()
if
err
!=
nil
{
return
nil
,
err
}
if
!
found
{
unique
=
false
recursive
,
_
,
err
:=
req
.
Option
(
"recursive"
)
.
Bool
()
if
err
!=
nil
{
return
nil
,
err
}
recursive
,
found
,
err
:=
req
.
Option
(
"
recursive
"
)
.
Bool
()
edges
,
_
,
err
:=
req
.
Option
(
"
edges
"
)
.
Bool
()
if
err
!=
nil
{
return
nil
,
err
}
if
!
found
{
recursive
=
false
objs
,
err
:=
objectsForPaths
(
n
,
req
.
Arguments
())
if
err
!=
nil
{
return
nil
,
err
}
return
getRefs
(
n
,
req
.
Arguments
(),
unique
,
recursive
)
},
Type
:
KeyList
{},
Marshalers
:
cmds
.
MarshalerMap
{
cmds
.
Text
:
KeyListTextMarshaler
,
piper
,
pipew
:=
io
.
Pipe
()
eptr
:=
&
ErrPassThroughReader
{
R
:
piper
}
go
func
()
{
defer
pipew
.
Close
()
rw
:=
RefWriter
{
W
:
pipew
,
DAG
:
n
.
DAG
,
Ctx
:
n
.
Context
(),
Unique
:
unique
,
PrintEdge
:
edges
,
Recursive
:
recursive
,
}
for
_
,
o
:=
range
objs
{
if
_
,
err
:=
rw
.
WriteRefs
(
o
);
err
!=
nil
{
eptr
.
SetError
(
err
)
}
}
}()
return
eptr
,
nil
},
}
func
getRefs
(
n
*
core
.
IpfsNode
,
paths
[]
string
,
unique
,
recursive
bool
)
(
*
KeyList
,
error
)
{
var
refsSeen
map
[
u
.
Key
]
bool
if
unique
{
refsSeen
=
make
(
map
[
u
.
Key
]
bool
)
func
objectsForPaths
(
n
*
core
.
IpfsNode
,
paths
[]
string
)
([]
*
dag
.
Node
,
error
)
{
objects
:=
make
([]
*
dag
.
Node
,
len
(
paths
))
for
i
,
p
:=
range
paths
{
o
,
err
:=
n
.
Resolver
.
ResolvePath
(
p
)
if
err
!=
nil
{
return
nil
,
err
}
objects
[
i
]
=
o
}
return
objects
,
nil
}
// ErrPassThroughReader is a reader that may return an externally set error.
type
ErrPassThroughReader
struct
{
R
io
.
ReadCloser
err
error
sync
.
RWMutex
}
func
(
r
*
ErrPassThroughReader
)
Error
()
error
{
r
.
RLock
()
defer
r
.
RUnlock
()
return
r
.
err
}
func
(
r
*
ErrPassThroughReader
)
SetError
(
err
error
)
{
r
.
Lock
()
r
.
err
=
err
r
.
Unlock
()
}
func
(
r
*
ErrPassThroughReader
)
Read
(
buf
[]
byte
)
(
int
,
error
)
{
err
:=
r
.
Error
()
if
err
!=
nil
{
return
0
,
err
}
return
r
.
R
.
Read
(
buf
)
}
func
(
r
*
ErrPassThroughReader
)
Close
()
error
{
err1
:=
r
.
R
.
Close
()
err2
:=
r
.
Error
()
if
err2
!=
nil
{
return
err2
}
return
err1
}
type
RefWriter
struct
{
W
io
.
Writer
DAG
dag
.
DAGService
Ctx
context
.
Context
refs
:=
make
([]
u
.
Key
,
0
)
Unique
bool
Recursive
bool
PrintEdge
bool
seen
map
[
u
.
Key
]
struct
{}
}
// WriteRefs writes refs of the given object to the underlying writer.
func
(
rw
*
RefWriter
)
WriteRefs
(
n
*
dag
.
Node
)
(
int
,
error
)
{
nkey
,
err
:=
n
.
Key
()
if
err
!=
nil
{
return
0
,
err
}
if
rw
.
skip
(
nkey
)
{
return
0
,
nil
}
count
:=
0
for
_
,
l
:=
range
n
.
Links
{
lk
:=
u
.
Key
(
l
.
Hash
)
if
rw
.
skip
(
lk
)
{
continue
}
if
err
:=
rw
.
WriteEdge
(
nkey
,
lk
);
err
!=
nil
{
return
count
,
err
}
count
++
for
_
,
path
:=
range
paths
{
object
,
err
:=
n
.
Resolver
.
ResolvePath
(
path
)
if
!
rw
.
Recursive
{
continue
}
child
,
err
:=
l
.
GetNode
(
rw
.
DAG
)
if
err
!=
nil
{
return
nil
,
err
return
count
,
err
}
refs
,
err
=
addRefs
(
n
,
object
,
refs
,
refsSeen
,
recursive
)
c
,
err
:=
rw
.
WriteRefs
(
child
)
count
+=
c
if
err
!=
nil
{
return
nil
,
err
return
count
,
err
}
}
return
&
KeyList
{
refs
},
nil
return
count
,
nil
}
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
)
if
recursive
&&
!
found
{
child
,
err
:=
n
.
DAG
.
Get
(
u
.
Key
(
link
.
Hash
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"cannot retrieve %s (%s)"
,
link
.
Hash
.
B58String
(),
err
)
}
// skip returns whether to skip a key
func
(
rw
*
RefWriter
)
skip
(
k
u
.
Key
)
bool
{
if
!
rw
.
Unique
{
return
false
}
refs
,
err
=
addRefs
(
n
,
child
,
refs
,
refsSeen
,
recursive
)
if
err
!=
nil
{
return
nil
,
err
}
}
if
rw
.
seen
==
nil
{
rw
.
seen
=
make
(
map
[
u
.
Key
]
struct
{})
}
return
refs
,
nil
_
,
found
:=
rw
.
seen
[
k
]
if
!
found
{
rw
.
seen
[
k
]
=
struct
{}{}
}
return
found
}
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
[
key
]
if
found
{
return
true
,
refs
// Write one edge
func
(
rw
*
RefWriter
)
WriteEdge
(
from
,
to
u
.
Key
)
error
{
if
rw
.
Ctx
!=
nil
{
select
{
case
<-
rw
.
Ctx
.
Done
()
:
// just in case.
return
rw
.
Ctx
.
Err
()
default
:
}
refsSeen
[
key
]
=
true
}
refs
=
append
(
refs
,
key
)
return
false
,
refs
var
s
string
if
rw
.
PrintEdge
{
s
=
from
.
Pretty
()
+
" -> "
}
s
+=
to
.
Pretty
()
+
"
\n
"
if
_
,
err
:=
rw
.
W
.
Write
([]
byte
(
s
));
err
!=
nil
{
return
err
}
return
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment