@@ -5,6 +5,7 @@ import { DepGraphBuilder } from '../core/builder';
5
5
6
6
export {
7
7
depTreeToGraph ,
8
+ graphToDepTree ,
8
9
DepTree ,
9
10
} ;
10
11
@@ -17,6 +18,7 @@ interface DepTreeDep {
17
18
}
18
19
19
20
interface DepTree extends DepTreeDep {
21
+ packageFormatVersion ?: string ;
20
22
targetOS ?: {
21
23
name : string ;
22
24
version : string ;
@@ -152,6 +154,77 @@ async function shortenNodeIds(depGraph: types.DepGraphInternal): Promise<types.D
152
154
return builder . build ( ) ;
153
155
}
154
156
157
+ async function graphToDepTree ( depGraphInterface : types . DepGraph , pkgType : string ) : Promise < DepTree > {
158
+ const depGraph = ( depGraphInterface as types . DepGraphInternal ) ;
159
+
160
+ // TODO: implement cycles support
161
+ if ( depGraph . hasCycles ( ) ) {
162
+ throw new Error ( 'Conversion to DepTree does not support cyclic graphs yet' ) ;
163
+ }
164
+
165
+ const depTree = await buildSubtree ( depGraph , depGraph . rootNodeId ) ;
166
+
167
+ depTree . packageFormatVersion = constructPackageFormatVersion ( pkgType ) ;
168
+
169
+ const targetOS = constructTargetOS ( depGraph ) ;
170
+ if ( targetOS ) {
171
+ depTree . targetOS = targetOS ;
172
+ }
173
+
174
+ return depTree ;
175
+ }
176
+
177
+ function constructPackageFormatVersion ( pkgType : string ) : string {
178
+ if ( pkgType === 'maven' ) {
179
+ pkgType = 'mvn' ;
180
+ }
181
+ return `${ pkgType } :0.0.1` ;
182
+ }
183
+
184
+ function constructTargetOS ( depGraph : types . DepGraph ) : { name : string ; version : string ; } {
185
+ if ( [ 'apk' , 'apt' , 'deb' , 'rpm' ] . indexOf ( depGraph . pkgManager . name ) === - 1 ) {
186
+ // .targetOS is undefined unless its a linux pkgManager
187
+ return ;
188
+ }
189
+
190
+ if ( ! depGraph . pkgManager . repositories
191
+ || ! depGraph . pkgManager . repositories . length
192
+ || ! depGraph . pkgManager . repositories [ 0 ] . alias ) {
193
+ throw new Error ( 'Incomplete .pkgManager, could not create .targetOS' ) ;
194
+ }
195
+
196
+ const [ name , version ] = depGraph . pkgManager . repositories [ 0 ] . alias . split ( ':' ) ;
197
+ return { name, version } ;
198
+ }
199
+
200
+ async function buildSubtree ( depGraph : types . DepGraphInternal , nodeId : string ) : Promise < DepTree > {
201
+ const nodePkg = depGraph . getNodePkg ( nodeId ) ;
202
+ const depTree : DepTree = { } ;
203
+ depTree . name = nodePkg . name ;
204
+ depTree . version = nodePkg . version ;
205
+
206
+ const depInstanceIds = depGraph . getNodeDepsNodeIds ( nodeId ) ;
207
+ if ( ! depInstanceIds || depInstanceIds . length === 0 ) {
208
+ return depTree ;
209
+ }
210
+
211
+ for ( const depInstId of depInstanceIds ) {
212
+ const subtree = await buildSubtree ( depGraph , depInstId ) ;
213
+ if ( ! subtree ) {
214
+ continue ;
215
+ }
216
+
217
+ if ( ! depTree . dependencies ) {
218
+ depTree . dependencies = { } ;
219
+ }
220
+
221
+ depTree . dependencies [ subtree . name ] = subtree ;
222
+ }
223
+
224
+ await spinTheEventLoop ( ) ;
225
+ return depTree ;
226
+ }
227
+
155
228
async function spinTheEventLoop ( ) {
156
229
return new Promise ( ( resolve ) => setImmediate ( resolve ) ) ;
157
230
}
0 commit comments