MCPcopy Index your code
hub / github.com/devcontainers/cli / _buildDependencyGraph

Function _buildDependencyGraph

src/spec-configuration/containerFeaturesOrder.ts:345–477  ·  view source on GitHub ↗
(
	params: CommonParams,
	processFeature: (userFeature: DevContainerFeature) => Promise<FeatureSet | undefined>,
	worklist: FNode[],
	acc: FNode[],
	lockfile: Lockfile | undefined)

Source from the content-addressed store, hash-verified

343}
344
345async function _buildDependencyGraph(
346 params: CommonParams,
347 processFeature: (userFeature: DevContainerFeature) => Promise<FeatureSet | undefined>,
348 worklist: FNode[],
349 acc: FNode[],
350 lockfile: Lockfile | undefined): Promise<DependencyGraph> {
351 const { output } = params;
352
353 while (worklist.length > 0) {
354 const current = worklist.shift()!;
355
356 output.write(`Resolving Feature dependencies for '${current.userFeatureId}'...`, LogLevel.Info);
357
358 const processedFeature = await processFeature(current);
359 if (!processedFeature) {
360 throw new Error(`ERR: Feature '${current.userFeatureId}' could not be processed. You may not have permission to access this Feature, or may not be logged in. If the issue persists, report this to the Feature author.`);
361 }
362
363 // Set the processed FeatureSet object onto Node.
364 current.featureSet = processedFeature;
365
366 // If the current Feature is already in the accumulator, skip it.
367 // This stops cycles but doesn't report them.
368 // Cycles/inconsistencies are thrown as errors in the next stage (rounds).
369 if (acc.some(f => equals(params, f, current))) {
370 continue;
371 }
372
373 const type = processedFeature.sourceInformation.type;
374 let metadata: Feature | undefined;
375 // Switch on the source type of the provided Feature.
376 // Retrieving the metadata for the Feature (the contents of 'devcontainer-feature.json')
377 switch (type) {
378 case 'oci':
379 metadata = await getOCIFeatureMetadata(params, current);
380 break;
381
382 case 'file-path':
383 const filePath = (current.featureSet.sourceInformation as FilePathSourceInformation).resolvedFilePath;
384 const metadataFilePath = path.join(filePath, DEVCONTAINER_FEATURE_FILE_NAME);
385 if (!isLocalFile(filePath)) {
386 throw new Error(`Metadata file '${metadataFilePath}' cannot be read for Feature '${current.userFeatureId}'.`);
387 }
388 const serialized = (await readLocalFile(metadataFilePath)).toString();
389 if (serialized) {
390 metadata = jsonc.parse(serialized) as Feature;
391 }
392 break;
393
394 case 'direct-tarball':
395 const tarballUri = (processedFeature.sourceInformation as DirectTarballSourceInformation).tarballUri;
396 const expectedDigest = lockfile?.features[tarballUri]?.integrity;
397 metadata = await getTgzFeatureMetadata(params, current, expectedDigest);
398 break;
399
400 default:
401 // Legacy
402 // No dependency metadata to retrieve.

Callers 1

buildDependencyGraphFunction · 0.85

Calls 6

isLocalFileFunction · 0.90
equalsFunction · 0.85
getOCIFeatureMetadataFunction · 0.85
getTgzFeatureMetadataFunction · 0.85
processFeatureFunction · 0.70
writeMethod · 0.65

Tested by

no test coverage detected