refactor(manager/pip-compile): Move topological sort to utils (#27398)

This commit is contained in:
Norbert Szulc 2024-02-19 13:43:34 +01:00 committed by GitHub
parent 1ffa44c4fe
commit 82651110a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 28 deletions

View file

@ -1,4 +1,3 @@
import { Graph } from 'graph-data-structure';
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import { readLocalFile } from '../../../util/fs'; import { readLocalFile } from '../../../util/fs';
import { normalizeDepName } from '../../datasource/pypi/common'; import { normalizeDepName } from '../../datasource/pypi/common';
@ -11,7 +10,7 @@ import type {
PipCompileArgs, PipCompileArgs,
SupportedManagers, SupportedManagers,
} from './types'; } from './types';
import { generateMermaidGraph } from './utils'; import { generateMermaidGraph, sortPackageFiles } from './utils';
function matchManager(filename: string): SupportedManagers | 'unknown' { function matchManager(filename: string): SupportedManagers | 'unknown' {
if (filename.endsWith('setup.py')) { if (filename.endsWith('setup.py')) {
@ -178,32 +177,10 @@ export async function extractAllPackageFiles(
if (packageFiles.size === 0) { if (packageFiles.size === 0) {
return null; return null;
} }
const result: PackageFile[] = []; const result: PackageFile[] = sortPackageFiles(
const graph: ReturnType<typeof Graph> = Graph(); depsBetweenFiles,
depsBetweenFiles.forEach(({ sourceFile, outputFile }) => { packageFiles,
graph.addEdge(sourceFile, outputFile); );
});
const sorted = graph.topologicalSort();
for (const file of sorted) {
if (packageFiles.has(file)) {
const packageFile = packageFiles.get(file)!;
const sortedLockFiles = [];
// TODO(not7cd): this needs better test case
for (const lockFile of packageFile.lockFiles!) {
if (sorted.includes(lockFile)) {
sortedLockFiles.push(lockFile);
}
}
packageFile.lockFiles = sortedLockFiles;
result.push(packageFile);
}
}
// istanbul ignore if: should never happen
if (result.length !== packageFiles.size) {
throw new Error(
'pip-compile: topological sort failed to include all package files',
);
}
logger.debug( logger.debug(
'pip-compile: dependency graph:\n' + 'pip-compile: dependency graph:\n' +
generateMermaidGraph(depsBetweenFiles, lockFileArgs), generateMermaidGraph(depsBetweenFiles, lockFileArgs),

View file

@ -1,5 +1,38 @@
import { Graph } from 'graph-data-structure';
import type { PackageFile } from '../types';
import type { DependencyBetweenFiles, PipCompileArgs } from './types'; import type { DependencyBetweenFiles, PipCompileArgs } from './types';
export function sortPackageFiles(
depsBetweenFiles: DependencyBetweenFiles[],
packageFiles: Map<string, PackageFile>,
): PackageFile[] {
const result: PackageFile[] = [];
const graph: ReturnType<typeof Graph> = Graph();
depsBetweenFiles.forEach(({ sourceFile, outputFile }) => {
graph.addEdge(sourceFile, outputFile);
});
const sorted = graph.topologicalSort();
for (const file of sorted) {
if (packageFiles.has(file)) {
const packageFile = packageFiles.get(file)!;
const sortedLockFiles = [];
// TODO(not7cd): this needs better test case
for (const lockFile of packageFile.lockFiles!) {
if (sorted.includes(lockFile)) {
sortedLockFiles.push(lockFile);
}
}
packageFile.lockFiles = sortedLockFiles;
result.push(packageFile);
}
}
// istanbul ignore if: should never happen
if (result.length !== packageFiles.size) {
throw new Error('Topological sort failed to include all package files');
}
return result;
}
export function generateMermaidGraph( export function generateMermaidGraph(
depsBetweenFiles: DependencyBetweenFiles[], depsBetweenFiles: DependencyBetweenFiles[],
lockFileArgs: Map<string, PipCompileArgs>, lockFileArgs: Map<string, PipCompileArgs>,