@@ -2,6 +2,7 @@ package graphsplit
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
6
7
"io"
7
8
"io/ioutil"
@@ -19,6 +20,7 @@ import (
19
20
bstore "github.com/ipfs/go-ipfs-blockstore"
20
21
chunker "github.com/ipfs/go-ipfs-chunker"
21
22
offline "github.com/ipfs/go-ipfs-exchange-offline"
23
+ format "github.com/ipfs/go-ipld-format"
22
24
"github.com/ipfs/go-merkledag"
23
25
dag "github.com/ipfs/go-merkledag"
24
26
"github.com/ipfs/go-unixfs"
@@ -45,23 +47,101 @@ type Finfo struct {
45
47
SeekEnd int64
46
48
}
47
49
50
+ // file system tree node
51
+ type fsNode struct {
52
+ Name string
53
+ Hash string
54
+ Size uint64
55
+ Link []fsNode
56
+ }
57
+
58
+ type FSBuilder struct {
59
+ root * dag.ProtoNode
60
+ ds ipld.DAGService
61
+ }
62
+
63
+ func NewFSBuilder (root * dag.ProtoNode , ds ipld.DAGService ) * FSBuilder {
64
+ return & FSBuilder {root , ds }
65
+ }
66
+
67
+ func (b * FSBuilder ) Build () (* fsNode , error ) {
68
+ fsn , err := unixfs .FSNodeFromBytes (b .root .Data ())
69
+ if err != nil {
70
+ return nil , xerrors .Errorf ("input dag is not a unixfs node: %s" , err )
71
+ }
72
+
73
+ rootn := & fsNode {
74
+ Hash : b .root .Cid ().String (),
75
+ Size : fsn .FileSize (),
76
+ Link : []fsNode {},
77
+ }
78
+ if ! fsn .IsDir () {
79
+ return rootn , nil
80
+ }
81
+ for _ , ln := range b .root .Links () {
82
+ fn , err := b .getNodeByLink (ln )
83
+ if err != nil {
84
+ return nil , err
85
+ }
86
+ rootn .Link = append (rootn .Link , fn )
87
+ }
88
+
89
+ return rootn , nil
90
+ }
91
+
92
+ func (b * FSBuilder ) getNodeByLink (ln * format.Link ) (fn fsNode , err error ) {
93
+ ctx := context .Background ()
94
+ fn = fsNode {
95
+ Name : ln .Name ,
96
+ Hash : ln .Cid .String (),
97
+ Size : ln .Size ,
98
+ }
99
+ nd , err := b .ds .Get (ctx , ln .Cid )
100
+ if err != nil {
101
+ log .Warn (err )
102
+ return
103
+ }
104
+
105
+ nnd , ok := nd .(* dag.ProtoNode )
106
+ if ! ok {
107
+ err = xerrors .Errorf ("failed to transformed to dag.ProtoNode" )
108
+ return
109
+ }
110
+ fsn , err := unixfs .FSNodeFromBytes (nnd .Data ())
111
+ if err != nil {
112
+ log .Warnf ("input dag is not a unixfs node: %s" , err )
113
+ return
114
+ }
115
+ if ! fsn .IsDir () {
116
+ return
117
+ }
118
+ for _ , ln := range nnd .Links () {
119
+ node , err := b .getNodeByLink (ln )
120
+ if err != nil {
121
+ return node , err
122
+ }
123
+ fn .Link = append (fn .Link , node )
124
+ }
125
+ return
126
+ }
127
+
48
128
func BuildIpldGraph (ctx context.Context , fileList []Finfo , graphName , parentPath , carDir string , parallel int , cb GraphBuildCallback ) {
49
- node , err := buildIpldGraph (ctx , fileList , parentPath , carDir , parallel )
129
+ node , fsDetail , err := buildIpldGraph (ctx , fileList , parentPath , carDir , parallel )
50
130
if err != nil {
51
131
//log.Fatal(err)
52
132
cb .OnError (err )
53
133
return
54
134
}
55
- cb .OnSuccess (node , graphName )
135
+ cb .OnSuccess (node , graphName , fsDetail )
56
136
}
57
137
58
- func buildIpldGraph (ctx context.Context , fileList []Finfo , parentPath , carDir string , parallel int ) (ipld.Node , error ) {
138
+ func buildIpldGraph (ctx context.Context , fileList []Finfo , parentPath , carDir string , parallel int ) (ipld.Node , string , error ) {
59
139
bs2 := bstore .NewBlockstore (dss .MutexWrap (datastore .NewMapDatastore ()))
60
140
dagServ := merkledag .NewDAGService (blockservice .New (bs2 , offline .Exchange (bs2 )))
61
141
62
142
cidBuilder , err := merkledag .PrefixForCidVersion (0 )
63
143
if err != nil {
64
- return nil , err
144
+ return nil , "" , err
65
145
}
66
146
fileNodeMap := make (map [string ]* dag.ProtoNode )
67
147
dirNodeMap := make (map [string ]* dag.ProtoNode )
@@ -115,8 +195,11 @@ func buildIpldGraph(ctx context.Context, fileList []Finfo, parentPath, carDir st
115
195
// log.Info(item.Path)
116
196
// log.Infof("file name: %s, file size: %d, item size: %d, seek-start:%d, seek-end:%d", item.Name, item.Info.Size(), item.SeekEnd-item.SeekStart, item.SeekStart, item.SeekEnd)
117
197
dirStr := path .Dir (item .Path )
118
-
119
- if parentPath != "" && strings .HasPrefix (dirStr , parentPath ) {
198
+ parentPath = path .Clean (parentPath )
199
+ // when parent path equal target path, and the parent path is also a file path
200
+ if parentPath == path .Clean (item .Path ) {
201
+ dirStr = ""
202
+ } else if parentPath != "" && strings .HasPrefix (dirStr , parentPath ) {
120
203
dirStr = dirStr [len (parentPath ):]
121
204
}
122
205
@@ -175,7 +258,7 @@ func buildIpldGraph(ctx context.Context, fileList []Finfo, parentPath, carDir st
175
258
if isLinked (parentNode , dir ) {
176
259
parentNode , err = parentNode .UpdateNodeLink (dir , dirNode )
177
260
if err != nil {
178
- return nil , err
261
+ return nil , "" , err
179
262
}
180
263
dirNodeMap [parentKey ] = parentNode
181
264
} else {
@@ -197,7 +280,7 @@ func buildIpldGraph(ctx context.Context, fileList []Finfo, parentPath, carDir st
197
280
//car
198
281
carF , err := os .Create (path .Join (carDir , rootNode .Cid ().String ()+ ".car" ))
199
282
if err != nil {
200
- return nil , err
283
+ return nil , "" , err
201
284
}
202
285
defer carF .Close ()
203
286
selector := allSelector ()
@@ -206,13 +289,22 @@ func buildIpldGraph(ctx context.Context, fileList []Finfo, parentPath, carDir st
206
289
// cario := cario.NewCarIO()
207
290
// err = cario.WriteCar(context.Background(), bs2, rootNode.Cid(), selector, carF)
208
291
if err != nil {
209
- return nil , err
292
+ return nil , "" , err
210
293
}
211
294
log .Infof ("generate car file completed, time elapsed: %s" , time .Now ().Sub (genCarStartTime ))
212
295
296
+ fsBuilder := NewFSBuilder (rootNode , dagServ )
297
+ fsNode , err := fsBuilder .Build ()
298
+ if err != nil {
299
+ return nil , "" , err
300
+ }
301
+ fsNodeBytes , err := json .Marshal (fsNode )
302
+ if err != nil {
303
+ return nil , "" , err
304
+ }
213
305
//log.Info(dirNodeMap)
214
306
fmt .Println ("++++++++++++ finished to build ipld +++++++++++++" )
215
- return rootNode , nil
307
+ return rootNode , fmt . Sprintf ( "%s" , fsNodeBytes ), nil
216
308
}
217
309
218
310
func allSelector () ipldprime.Node {
0 commit comments