@@ -14,33 +14,81 @@ function dpath (p) {
14
14
15
15
module . exports = rpt
16
16
17
- function Node ( package , path ) {
17
+ rpt . Node = Node
18
+ rpt . Link = Link
19
+
20
+ var ID = 0
21
+ function Node ( package , path , cache ) {
22
+ if ( cache [ path ] )
23
+ return cache [ path ]
24
+
18
25
if ( ! ( this instanceof Node ) )
19
- return new Node ( package , path )
26
+ return new Node ( package , path , cache )
27
+
28
+ cache [ path ] = this
20
29
21
- debug ( 'Node' , dpath ( path ) , package && package . _id )
30
+ debug ( this . constructor . name , dpath ( path ) , package && package . _id )
31
+
32
+ this . id = ID ++
22
33
this . package = package
23
34
this . path = path
35
+ this . realpath = path
24
36
this . children = [ ]
25
37
}
26
38
Node . prototype . package = null
27
39
Node . prototype . path = ''
40
+ Node . prototype . realpath = ''
28
41
Node . prototype . children = null
29
42
30
- function loadNode ( p , cb ) {
43
+
44
+
45
+ function Link ( package , path , realpath , cache ) {
46
+ if ( cache [ path ] )
47
+ return cache [ path ]
48
+
49
+ if ( ! ( this instanceof Link ) )
50
+ return new Link ( package , path , realpath )
51
+
52
+ cache [ path ] = this
53
+
54
+ debug ( this . constructor . name , dpath ( path ) , package && package . _id )
55
+
56
+ this . id = ID ++
57
+ this . path = path
58
+ this . realpath = realpath
59
+ this . package = package
60
+ this . target = new Node ( package , realpath , cache )
61
+ this . children = this . target . children
62
+ }
63
+ Link . prototype = Object . create ( Node . prototype , {
64
+ constructor : { value : Link }
65
+ } )
66
+ Link . prototype . target = null
67
+ Link . prototype . realpath = ''
68
+
69
+
70
+
71
+ function loadNode ( p , cache , cb ) {
31
72
debug ( 'loadNode' , dpath ( p ) )
32
73
fs . realpath ( p , function ( er , real ) {
33
74
if ( er )
34
75
return cb ( er )
35
76
debug ( 'realpath p=%j real=%j' , dpath ( p ) , dpath ( real ) )
36
77
var pj = path . resolve ( real , 'package.json' )
37
78
rpj ( pj , function ( er , package ) {
38
- cb ( er , new Node ( package || null , real ) )
79
+ package = package || null
80
+ var n
81
+ if ( p === real )
82
+ n = new Node ( package , real , cache )
83
+ else
84
+ n = new Link ( package , p , real , cache )
85
+
86
+ cb ( er , n )
39
87
} )
40
88
} )
41
89
}
42
90
43
- function loadChildren ( node , cb ) {
91
+ function loadChildren ( node , cache , cb ) {
44
92
debug ( 'loadChildren' , dpath ( node . path ) )
45
93
// don't let it be called more than once
46
94
cb = once ( cb )
@@ -60,7 +108,7 @@ function loadChildren (node, cb) {
60
108
61
109
kids . forEach ( function ( kid ) {
62
110
var p = path . resolve ( nm , kid )
63
- loadNode ( p , then )
111
+ loadNode ( p , cache , then )
64
112
} )
65
113
66
114
function then ( er , kid ) {
@@ -83,28 +131,30 @@ function sortChildren (node) {
83
131
} )
84
132
}
85
133
86
- function loadTree ( node , cb , did ) {
87
- did = did || Object . create ( null )
88
- debug ( 'loadTree' , dpath ( node . path ) , ! ! did [ node . path ] )
89
- if ( did [ node . path ] )
134
+ function loadTree ( node , did , cache , cb ) {
135
+ debug ( 'loadTree' , dpath ( node . path ) , ! ! cache [ node . path ] )
136
+
137
+ if ( did [ node . realpath ] ) {
90
138
return dz ( cb ) ( null , node )
139
+ }
91
140
92
- did [ node . path ] = true
141
+ did [ node . realpath ] = true
93
142
94
143
cb = once ( cb )
95
- loadChildren ( node , function ( er , node ) {
144
+ loadChildren ( node , cache , function ( er , node ) {
96
145
if ( er )
97
146
return cb ( er )
98
147
99
148
var kids = node . children . filter ( function ( kid ) {
100
- return ! did [ kid . path ]
149
+ return ! did [ kid . realpath ]
101
150
} )
151
+
102
152
var l = kids . length
103
153
if ( l === 0 )
104
154
return cb ( null , node )
105
155
106
- kids . forEach ( function ( kid ) {
107
- loadTree ( kid , then , did )
156
+ kids . forEach ( function ( kid , index ) {
157
+ loadTree ( kid , did , cache , then )
108
158
} )
109
159
110
160
function then ( er , kid ) {
@@ -118,11 +168,13 @@ function loadTree (node, cb, did) {
118
168
}
119
169
120
170
function rpt ( root , cb ) {
171
+ root = path . resolve ( root )
121
172
debug ( 'rpt' , dpath ( root ) )
122
- loadNode ( root , function ( er , node ) {
173
+ var cache = Object . create ( null )
174
+ loadNode ( root , cache , function ( er , node ) {
123
175
// if there's an error, it's fine, as long as we got a node
124
176
if ( ! node )
125
177
return cb ( er )
126
- loadTree ( node , cb )
178
+ loadTree ( node , { } , cache , cb )
127
179
} )
128
180
}
0 commit comments