14
14
15
15
import * as vscode from "vscode" ;
16
16
import * as fs from "fs/promises" ;
17
+ import * as path from "path" ;
17
18
import {
18
19
buildDirectoryFromWorkspacePath ,
19
20
execSwift ,
20
21
getErrorDescription ,
21
22
} from "./utilities/utilities" ;
22
- import checksum = require( "checksum" ) ;
23
23
24
24
/** Swift Package Manager contents */
25
25
export interface PackageContents {
@@ -152,6 +152,61 @@ function isError(state: SwiftPackageState): state is Error {
152
152
return state instanceof Error ;
153
153
}
154
154
155
+ /**
156
+ * Get version of WorkspaceStateDependency for displaying in the tree
157
+ * @param dependency
158
+ * @return real version | edited | local
159
+ */
160
+ export function dependencyVersion ( dependency : WorkspaceStateDependency ) : string {
161
+ return dependency . packageRef . kind === "fileSystem"
162
+ ? "local"
163
+ : dependency . state . checkoutState ?. version ??
164
+ dependency . state . checkoutState ?. branch ??
165
+ "edited" ;
166
+ }
167
+
168
+ /**
169
+ * Get type of WorkspaceStateDependency for displaying in the tree: real version | edited | local
170
+ * @param dependency
171
+ * @return "local" | "remote" | "edited"
172
+ */
173
+ export function dependencyType (
174
+ dependency : WorkspaceStateDependency
175
+ ) : "local" | "remote" | "edited" {
176
+ return dependency . state . name === "edited"
177
+ ? "edited"
178
+ : dependency . packageRef . kind === "fileSystem"
179
+ ? "local"
180
+ : "remote" ;
181
+ }
182
+
183
+ /**
184
+ * Get type of WorkspaceStateDependency for displaying in the tree: real version | edited | local
185
+ * `edited`: dependency.state.path ?? workspacePath + Packages/ + dependency.subpath
186
+ * `local`: dependency.packageRef.location
187
+ * `remote`: buildDirectory + checkouts + dependency.packageRef.location
188
+ * @param dependency
189
+ * @return the package path based on the type
190
+ */
191
+ export function dependencyPackagePath (
192
+ dependency : WorkspaceStateDependency ,
193
+ workspaceFolder : string
194
+ ) : string {
195
+ const type = dependencyType ( dependency ) ;
196
+ let packagePath = "" ;
197
+ if ( type === "edited" ) {
198
+ packagePath =
199
+ dependency . state . path ?? path . join ( workspaceFolder , "Packages" , dependency . subpath ) ;
200
+ } else if ( type === "local" ) {
201
+ packagePath = dependency . state . path ?? dependency . packageRef . location ;
202
+ } else {
203
+ // remote
204
+ const buildDirectory = buildDirectoryFromWorkspacePath ( workspaceFolder , true ) ;
205
+ packagePath = path . join ( buildDirectory , "checkouts" , dependency . subpath ) ;
206
+ }
207
+ return packagePath ;
208
+ }
209
+
155
210
/**
156
211
* Class holding Swift Package Manager Package
157
212
*/
@@ -166,9 +221,7 @@ export class SwiftPackage implements PackageContents {
166
221
readonly folder : vscode . Uri ,
167
222
private contents : SwiftPackageState ,
168
223
public resolved : PackageResolved | undefined ,
169
- public plugins : PackagePlugin [ ] ,
170
- public resolvedContent : string | undefined ,
171
- public dependencySet : Set < string >
224
+ public plugins : PackagePlugin [ ]
172
225
) { }
173
226
174
227
/**
@@ -180,8 +233,7 @@ export class SwiftPackage implements PackageContents {
180
233
const contents = await SwiftPackage . loadPackage ( folder ) ;
181
234
const resolved = await SwiftPackage . loadPackageResolved ( folder ) ;
182
235
const plugins = await SwiftPackage . loadPlugins ( folder ) ;
183
- const resolvedContent = await SwiftPackage . loadPackageResolvedFile ( folder ) ;
184
- return new SwiftPackage ( folder , contents , resolved , plugins , resolvedContent , new Set ( ) ) ;
236
+ return new SwiftPackage ( folder , contents , resolved , plugins ) ;
185
237
}
186
238
187
239
/**
@@ -217,19 +269,10 @@ export class SwiftPackage implements PackageContents {
217
269
}
218
270
}
219
271
220
- static async loadPackageResolvedFile ( folder : vscode . Uri ) : Promise < string | undefined > {
272
+ static async loadPackageResolved ( folder : vscode . Uri ) : Promise < PackageResolved | undefined > {
221
273
try {
222
274
const uri = vscode . Uri . joinPath ( folder , "Package.resolved" ) ;
223
275
const contents = await fs . readFile ( uri . fsPath , "utf8" ) ;
224
- return contents ;
225
- } catch {
226
- return undefined ;
227
- }
228
- }
229
-
230
- static async loadPackageResolved ( folder : vscode . Uri ) : Promise < PackageResolved | undefined > {
231
- try {
232
- const contents = await SwiftPackage . loadPackageResolvedFile ( folder ) ;
233
276
if ( contents === undefined ) {
234
277
return undefined ;
235
278
}
@@ -273,34 +316,6 @@ export class SwiftPackage implements PackageContents {
273
316
}
274
317
}
275
318
276
- async packageResovledHasChanged ( action : any ) : Promise < boolean > {
277
- console . log ( action ) ;
278
- const resolvedContent = await SwiftPackage . loadPackageResolvedFile ( this . folder ) ;
279
-
280
- console . log ( resolvedContent ) ;
281
- console . log ( this . resolvedContent ) ;
282
-
283
- if ( resolvedContent === undefined ) {
284
- return false ;
285
- }
286
- // deletion --> creation --> modification
287
- // r undefined exists exists
288
- // pr exists undefined exists
289
-
290
- if ( this . resolvedContent === undefined ) {
291
- return true ;
292
- }
293
-
294
- const oldChecksum = checksum ( resolvedContent ) ;
295
- const newChecksum = checksum ( this . resolvedContent ) ;
296
-
297
- if ( oldChecksum !== newChecksum ) {
298
- return true ;
299
- }
300
-
301
- return false ;
302
- }
303
-
304
319
/**
305
320
* Load workspace-state.json file for swift package
306
321
* @returns Workspace state
@@ -320,24 +335,79 @@ export class SwiftPackage implements PackageContents {
320
335
}
321
336
322
337
/**
323
- * Run `swift package describe` and return results
324
- * @param folder folder package is in
325
- * @returns results of `swift package describe`
338
+ * tranverse the dependency tree
339
+ * in each node, call `swift package describe` to get the child dependencies and do it recursively
340
+ * @returns all dependencies in flat list
326
341
*/
327
- async resolveDependencyGraph ( ) : Promise < Set < string > > {
328
- return this . dependencySet ;
329
- }
342
+ async resolveDependencyGraph ( ) : Promise < WorkspaceStateDependency [ ] > {
343
+ const workspaceState = await this . loadWorkspaceState ( ) ;
344
+ const workspaceStateDependencies = workspaceState ?. object . dependencies ?? [ ] ;
345
+
346
+ if ( workspaceStateDependencies . length === 0 ) {
347
+ return [ ] ;
348
+ }
330
349
331
- updateDependencySetWithStdout ( stdout : string ) : void {
332
- const lines = stdout
333
- . split ( "\n" )
334
- . filter ( item => item !== "" )
335
- . map ( item => item . trim ( ) ) ;
336
- this . updateDependencySet ( new Set ( lines ?? [ ] ) ) ;
350
+ const contents = this . contents as PackageContents ;
351
+ console . log ( "== resolve graph begin" ) ;
352
+ const showingDependencies = new Set < string > ( ) ;
353
+ await this . getChildDependencies ( contents , workspaceStateDependencies , showingDependencies ) ;
354
+
355
+ console . log ( "== resolve graph done" ) ;
356
+
357
+ // filter workspaceStateDependencies that in showingDependencies
358
+ return workspaceStateDependencies . filter ( dependency =>
359
+ showingDependencies . has ( dependency . packageRef . identity )
360
+ ) ;
361
+
362
+ // this can filter out dependencies that are not in the workspace state
363
+ // filter workspaceStateDependencies that not in showingDependencies
364
+ //const unusedPackages = workspaceStateDependencies.filter(
365
+ // dependency => !showingDependencies.has(dependency.packageRef.identity)
366
+ //);
337
367
}
338
368
339
- updateDependencySet ( dependencySet : Set < string > ) : void {
340
- this . dependencySet = dependencySet ;
369
+ /**
370
+ * tranverse the dependency tree
371
+ * @param dependency current node
372
+ * @param workspaceStateDependencies all dependencies in workspace-state.json
373
+ * @param showingDependencies result of dependencies that are showing in the tree
374
+ * @returns
375
+ */
376
+ private async getChildDependencies (
377
+ dependency : PackageContents ,
378
+ workspaceStateDependencies : WorkspaceStateDependency [ ] ,
379
+ showingDependencies : Set < string >
380
+ ) {
381
+ for ( let i = 0 ; i < dependency . dependencies . length ; i ++ ) {
382
+ const childDependency = dependency . dependencies [ i ] ;
383
+ if ( showingDependencies . has ( childDependency . identity ) ) {
384
+ return ;
385
+ }
386
+ showingDependencies . add ( childDependency . identity ) ;
387
+ const workspaceStateDependency = workspaceStateDependencies . find (
388
+ workspaceStateDependency =>
389
+ workspaceStateDependency . packageRef . identity === childDependency . identity
390
+ ) ;
391
+ if ( workspaceStateDependency ) {
392
+ showingDependencies . add ( workspaceStateDependency . packageRef . identity ) ;
393
+ }
394
+
395
+ if ( workspaceStateDependency === undefined ) {
396
+ return ;
397
+ }
398
+
399
+ const packagePath = dependencyPackagePath ( workspaceStateDependency , this . folder . fsPath ) ;
400
+
401
+ const childDependencyContents = ( await SwiftPackage . loadPackage (
402
+ vscode . Uri . file ( packagePath )
403
+ ) ) as PackageContents ;
404
+
405
+ await this . getChildDependencies (
406
+ childDependencyContents ,
407
+ workspaceStateDependencies ,
408
+ showingDependencies
409
+ ) ;
410
+ }
341
411
}
342
412
343
413
/** Reload swift package */
@@ -347,7 +417,6 @@ export class SwiftPackage implements PackageContents {
347
417
348
418
/** Reload Package.resolved file */
349
419
public async reloadPackageResolved ( ) {
350
- this . resolvedContent = await SwiftPackage . loadPackageResolvedFile ( this . folder ) ;
351
420
this . resolved = await SwiftPackage . loadPackageResolved ( this . folder ) ;
352
421
}
353
422
0 commit comments