@@ -5,10 +5,10 @@ const log = debug('exporter')
5
5
log . err = debug ( 'exporter:error' )
6
6
const UnixFS = require ( 'ipfs-unixfs' )
7
7
const series = require ( 'run-series' )
8
- const async = require ( 'async' )
9
8
const Readable = require ( 'readable-stream' ) . Readable
10
9
const pathj = require ( 'path' )
11
10
const util = require ( 'util' )
11
+ const fieldtrip = require ( 'field-trip' )
12
12
13
13
exports = module . exports = Exporter
14
14
@@ -25,11 +25,12 @@ function Exporter (hash, dagService, options) {
25
25
26
26
this . _read = ( n ) => { }
27
27
28
- let fileExporter = ( node , name , callback ) => {
28
+ let fileExporter = ( node , name , done ) => {
29
29
let init
30
30
31
- if ( ! callback ) { callback = function noop ( ) { } }
31
+ if ( ! done ) throw new Error ( 'done must be set' )
32
32
33
+ // Logic to export a single (possibly chunked) unixfs file.
33
34
var rs = new Readable ( )
34
35
if ( node . links . length === 0 ) {
35
36
const unmarshaledData = UnixFS . unmarshal ( node . data )
@@ -43,8 +44,7 @@ function Exporter (hash, dagService, options) {
43
44
rs . push ( null )
44
45
}
45
46
this . push ( { content : rs , path : name } )
46
- callback ( )
47
- return
47
+ done ( )
48
48
} else {
49
49
init = false
50
50
rs . _read = ( ) => {
@@ -57,7 +57,7 @@ function Exporter (hash, dagService, options) {
57
57
return ( cb ) => {
58
58
dagService . get ( link . hash , ( err , res ) => {
59
59
if ( err ) {
60
- cb ( err )
60
+ return cb ( err )
61
61
}
62
62
var unmarshaledData = UnixFS . unmarshal ( res . data )
63
63
rs . push ( unmarshaledData . data )
@@ -67,26 +67,28 @@ function Exporter (hash, dagService, options) {
67
67
} )
68
68
series ( array , ( err , res ) => {
69
69
if ( err ) {
70
- callback ( )
70
+ rs . emit ( 'error' , err )
71
71
return
72
72
}
73
73
rs . push ( null )
74
- callback ( )
75
74
return
76
75
} )
77
76
}
78
77
this . push ( { content : rs , path : name } )
79
- callback ( )
80
- return
78
+ done ( )
81
79
}
82
80
}
83
81
84
- let dirExporter = ( node , name , callback ) => {
82
+ // Logic to export a unixfs directory.
83
+ let dirExporter = ( node , name , add , done ) => {
85
84
let init
86
85
87
- if ( ! callback ) { callback = function noop ( ) { } }
86
+ if ( ! add ) throw new Error ( 'add must be set' )
87
+ if ( ! done ) throw new Error ( 'done must be set' )
88
88
89
89
var rs = new Readable ( )
90
+
91
+ // Directory has no links
90
92
if ( node . links . length === 0 ) {
91
93
init = false
92
94
rs . _read = ( ) => {
@@ -98,49 +100,45 @@ function Exporter (hash, dagService, options) {
98
100
rs . push ( null )
99
101
}
100
102
this . push ( { content : null , path : name } )
101
- callback ( )
102
- return
103
+ done ( )
103
104
} else {
104
- async . forEachSeries ( node . links , ( link , callback ) => {
105
- dagService . get ( link . hash , ( err , res ) => {
106
- if ( err ) {
107
- callback ( err )
108
- }
109
- var unmarshaledData = UnixFS . unmarshal ( res . data )
110
- if ( unmarshaledData . type === 'file' ) {
111
- return ( fileExporter ( res , pathj . join ( name , link . name ) , callback ) )
112
- }
113
- if ( unmarshaledData . type === 'directory' ) {
114
- return ( dirExporter ( res , pathj . join ( name , link . name ) , callback ) )
115
- }
116
- callback ( )
117
- } )
118
- } , ( err ) => {
119
- if ( err ) {
120
- callback ( )
121
- return
122
- }
123
- callback ( )
124
- return
105
+ node . links . forEach ( ( link ) => {
106
+ add ( { path : pathj . join ( name , link . name ) , hash : link . hash } )
125
107
} )
108
+ done ( )
126
109
}
127
110
}
128
111
129
- dagService . get ( hash , ( err , fetchedNode ) => {
112
+ // Traverse the DAG asynchronously
113
+ var self = this
114
+ fieldtrip ( [ { path : hash , hash : hash } ] , visit , ( err ) => {
130
115
if ( err ) {
131
- this . emit ( 'error' , err )
116
+ self . emit ( 'error' , err )
132
117
return
133
118
}
134
- const data = UnixFS . unmarshal ( fetchedNode . data )
135
- const type = data . type
136
-
137
- if ( type === 'directory' ) {
138
- dirExporter ( fetchedNode , hash )
139
- }
140
- if ( type === 'file' ) {
141
- fileExporter ( fetchedNode , hash )
142
- }
119
+ self . push ( null )
143
120
} )
144
121
122
+ // Visit function: called once per node in the exported graph
123
+ function visit ( item , add , done ) {
124
+ dagService . get ( item . hash , ( err , fetchedNode ) => {
125
+ if ( err ) {
126
+ self . emit ( 'error' , err )
127
+ return
128
+ }
129
+
130
+ const data = UnixFS . unmarshal ( fetchedNode . data )
131
+ const type = data . type
132
+
133
+ if ( type === 'directory' ) {
134
+ dirExporter ( fetchedNode , item . path , add , done )
135
+ }
136
+
137
+ if ( type === 'file' ) {
138
+ fileExporter ( fetchedNode , item . path , done )
139
+ }
140
+ } )
141
+ }
142
+
145
143
return this
146
144
}
0 commit comments