From ab7ad7300f4236098fd5882f253dde1843363d9e Mon Sep 17 00:00:00 2001 From: Georgiana-Elena Maxim Date: Tue, 23 Apr 2024 15:35:30 +0300 Subject: [PATCH] feat: [OSM-1040] switched to config object as find files function param --- src/lib/find-files.ts | 85 +++++++----- src/lib/plugins/get-deps-from-plugin.ts | 8 +- src/lib/plugins/get-extra-project-count.ts | 10 +- src/lib/plugins/get-single-plugin-result.ts | 3 +- test/tap/find-files.test.ts | 145 +++++++++----------- 5 files changed, 125 insertions(+), 126 deletions(-) diff --git a/src/lib/find-files.ts b/src/lib/find-files.ts index d58a36223a9..5da23282775 100644 --- a/src/lib/find-files.ts +++ b/src/lib/find-files.ts @@ -1,8 +1,9 @@ import * as fs from 'fs'; import * as pathLib from 'path'; -const sortBy = require('lodash.sortby'); -const groupBy = require('lodash.groupby'); +import * as sortBy from 'lodash.sortby'; +import * as groupBy from 'lodash.groupby'; +import * as assign from 'lodash.assign'; import { detectPackageManagerFromFile } from './detect'; import * as debugModule from 'debug'; import { @@ -53,6 +54,30 @@ interface FindFilesRes { const ignoreFolders = ['node_modules', '.build']; +interface FindFilesConfig { + path: string; + ignore?: string[]; + filter?: string[]; + levelsDeep?: number; + featureFlags?: Set; +} + +type DefaultFindConfig = { + path: string; + ignore: string[]; + filter: string[]; + levelsDeep: number; + featureFlags: Set; +}; + +const defaultFindConfig: DefaultFindConfig = { + path: '', + ignore: [], + filter: [], + levelsDeep: 4, + featureFlags: new Set(), +}; + /** * Find all files in given search path. Returns paths to files found. * @@ -61,47 +86,36 @@ const ignoreFolders = ['node_modules', '.build']; * @param filter (optional) file names to find. If not provided all files are returned. * @param levelsDeep (optional) how many levels deep to search, defaults to two, this path and one sub directory. */ -export async function find( - path: string, - ignore: string[] = [], - filter: string[] = [], - featureFlags: Set = new Set(), - levelsDeep = 4, -): Promise { +export async function find(findConfig: FindFilesConfig): Promise { + const config: DefaultFindConfig = assign({}, defaultFindConfig, findConfig); const found: string[] = []; const foundAll: string[] = []; // ensure we ignore find against node_modules path and .build folder for swift. - if (path.endsWith('node_modules') || path.endsWith('/.build')) { + if (config.path.endsWith('node_modules') || config.path.endsWith('/.build')) { return { files: found, allFilesFound: foundAll }; } // ensure dependencies folders is always ignored for (const folder of ignoreFolders) { - if (!ignore.includes(folder)) { - ignore.push(folder); + if (!config.ignore.includes(folder)) { + config.ignore.push(folder); } } try { - if (levelsDeep < 0) { + if (config.levelsDeep < 0) { return { files: found, allFilesFound: foundAll }; } else { - levelsDeep--; + config.levelsDeep--; } - const fileStats = await getStats(path); + const fileStats = await getStats(config.path); if (fileStats.isDirectory()) { - const { files, allFilesFound } = await findInDirectory( - path, - ignore, - filter, - featureFlags, - levelsDeep, - ); + const { files, allFilesFound } = await findInDirectory(config); found.push(...files); foundAll.push(...allFilesFound); } else if (fileStats.isFile()) { - const fileFound = findFile(path, filter); + const fileFound = findFile(config.path, config.filter); if (fileFound) { found.push(fileFound); foundAll.push(fileFound); @@ -116,11 +130,13 @@ export async function find( ); } return { - files: filterForDefaultManifests(found, featureFlags), + files: filterForDefaultManifests(found, config.featureFlags), allFilesFound: foundAll, }; } catch (err) { - throw new Error(`Error finding files in path '${path}'.\n${err.message}`); + throw new Error( + `Error finding files in path '${config.path}'.\n${err.message}`, + ); } } @@ -137,22 +153,23 @@ function findFile(path: string, filter: string[] = []): string | null { } async function findInDirectory( - path: string, - ignore: string[] = [], - filter: string[] = [], - featureFlags: Set = new Set(), - levelsDeep = 4, + findConfig: FindFilesConfig, ): Promise { - const files = await readDirectory(path); + const config: DefaultFindConfig = assign({}, defaultFindConfig, findConfig); + const files = await readDirectory(config.path); const toFind = files - .filter((file) => !ignore.includes(file)) + .filter((file) => !config.ignore.includes(file)) .map((file) => { - const resolvedPath = pathLib.resolve(path, file); + const resolvedPath = pathLib.resolve(config.path, file); if (!fs.existsSync(resolvedPath)) { debug('File does not seem to exist, skipping: ', file); return { files: [], allFilesFound: [] }; } - return find(resolvedPath, ignore, filter, featureFlags, levelsDeep); + const findconfig = { + ...config, + path: resolvedPath, + }; + return find(findconfig); }); const found = await Promise.all(toFind); diff --git a/src/lib/plugins/get-deps-from-plugin.ts b/src/lib/plugins/get-deps-from-plugin.ts index d379748182e..13c4039a278 100644 --- a/src/lib/plugins/get-deps-from-plugin.ts +++ b/src/lib/plugins/get-deps-from-plugin.ts @@ -46,13 +46,13 @@ export async function getDepsFromPlugin( const levelsDeep = options.detectionDepth; const ignore = options.exclude ? options.exclude.split(',') : []; - const { files: targetFiles, allFilesFound } = await find( - root, + const { files: targetFiles, allFilesFound } = await find({ + path: root, ignore, - multiProjectProcessors[scanType].files, + filter: multiProjectProcessors[scanType].files, featureFlags, levelsDeep, - ); + }); debug( `auto detect manifest files, found ${targetFiles.length}`, targetFiles, diff --git a/src/lib/plugins/get-extra-project-count.ts b/src/lib/plugins/get-extra-project-count.ts index 15722f4abbf..a923d9f83c7 100644 --- a/src/lib/plugins/get-extra-project-count.ts +++ b/src/lib/plugins/get-extra-project-count.ts @@ -19,11 +19,11 @@ export async function getExtraProjectCount( return inspectResult.plugin.meta.allSubProjectNames.length; } try { - const { files: extraTargetFiles } = await find( - root, - [], - AUTO_DETECTABLE_FILES, - ); + const { files: extraTargetFiles } = await find({ + path: root, + ignore: [], + filter: AUTO_DETECTABLE_FILES, + }); const foundProjectsCount = extraTargetFiles.length > 1 ? extraTargetFiles.length - 1 : undefined; return foundProjectsCount; diff --git a/src/lib/plugins/get-single-plugin-result.ts b/src/lib/plugins/get-single-plugin-result.ts index 253c3ef5c56..2b692389069 100644 --- a/src/lib/plugins/get-single-plugin-result.ts +++ b/src/lib/plugins/get-single-plugin-result.ts @@ -10,8 +10,7 @@ export async function getSinglePluginResult( options: Options & (TestOptions | MonitorOptions), targetFile?: string, ): Promise { - let plugin: types.Plugin; - plugin = plugins.loadPlugin(options.packageManager); + const plugin: types.Plugin = plugins.loadPlugin(options.packageManager); const moduleInfo = ModuleInfo(plugin, options.policy); const inspectRes: pluginApi.InspectResult = await moduleInfo.inspect( root, diff --git a/test/tap/find-files.test.ts b/test/tap/find-files.test.ts index 8411cd8c4db..c2d2410631b 100644 --- a/test/tap/find-files.test.ts +++ b/test/tap/find-files.test.ts @@ -7,13 +7,10 @@ const testFixture = getFixturePath('find-files'); test('find all files in test fixture', async (t) => { // six levels deep to find all - const { files: result, allFilesFound } = await find( - testFixture, - [], - [], - new Set([]), - 6, - ); + const { files: result, allFilesFound } = await find({ + path: testFixture, + levelsDeep: 6, + }); const expected = [ path.join( testFixture, @@ -76,13 +73,11 @@ test('find all files in test fixture', async (t) => { test('find all files in test fixture ignoring node_modules', async (t) => { // six levels deep to ensure node_modules is tested - const { files: result } = await find( - testFixture, - ['node_modules'], - [], - new Set([]), - 6, - ); + const { files: result } = await find({ + path: testFixture, + ignore: ['node_modules'], + levelsDeep: 6, + }); const expected = [ path.join( testFixture, @@ -112,13 +107,11 @@ test('find all files in test fixture ignoring node_modules', async (t) => { test('find package.json file in test fixture ignoring node_modules', async (t) => { // six levels deep to ensure node_modules is tested const nodeModulesPath = path.join(testFixture, 'node_modules'); - const { files: result } = await find( - nodeModulesPath, - [], - ['package.json'], - new Set([]), - 6, - ); + const { files: result } = await find({ + path: nodeModulesPath, + filter: ['package.json'], + levelsDeep: 6, + }); const expected = []; t.same(result.sort(), expected.sort(), 'should return expected file'); }); @@ -126,25 +119,21 @@ test('find package.json file in test fixture ignoring node_modules', async (t) = test('find Package.swift file in test fixture ignoring .build folder', async (t) => { // six levels deep to ensure .build is tested const nodeModulesPath = path.join(testFixture, '.build'); - const { files: result } = await find( - nodeModulesPath, - [], - ['Package.swift'], - new Set([]), - 6, - ); + const { files: result } = await find({ + path: nodeModulesPath, + filter: ['Package.swift'], + levelsDeep: 6, + }); const expected = []; t.same(result.sort(), expected.sort(), 'should return expected file'); }); test('find Package.swift file in test fixture ignoring test.build folder ', async (t) => { const nodeModulesPath = path.join(testFixture, 'swift', 'test.build'); - const { files: result } = await find( - nodeModulesPath, - [], - ['Package.swift'], - new Set([]), - 6, - ); + const { files: result } = await find({ + path: nodeModulesPath, + filter: ['Package.swift'], + levelsDeep: 6, + }); const expected = [ path.join(testFixture, 'swift', 'test.build', 'Package.swift'), ]; @@ -153,13 +142,11 @@ test('find Package.swift file in test fixture ignoring test.build folder ', asyn test('find package.json file in test fixture (by default ignoring node_modules)', async (t) => { // six levels deep to ensure node_modules is tested - const { files: result } = await find( - testFixture, - [], - ['package.json'], - new Set([]), - 6, - ); + const { files: result } = await find({ + path: testFixture, + filter: ['package.json'], + levelsDeep: 6, + }); const expected = [ path.join(testFixture, 'npm', 'package.json'), path.join(testFixture, 'npm-with-lockfile', 'package.json'), @@ -171,13 +158,11 @@ test('find package.json file in test fixture (by default ignoring node_modules)' test('find package-lock.json file in test fixture (ignore package.json in the same folder)', async (t) => { const npmLockfilePath = path.join(testFixture, 'npm-with-lockfile'); - const { files: result } = await find( - npmLockfilePath, - [], - ['package.json', 'package-lock.json'], - new Set([]), - 1, - ); + const { files: result } = await find({ + path: npmLockfilePath, + filter: ['package.json', 'package-lock.json'], + levelsDeep: 1, + }); const expected = [path.join(npmLockfilePath, 'package-lock.json')]; t.same(result.sort(), expected.sort(), 'should return expected file'); }); @@ -185,13 +170,11 @@ test('find package-lock.json file in test fixture (ignore package.json in the sa test('find build.gradle file in test fixture (ignore build.gradle in the same folder)', async (t) => { const buildGradle = path.join(testFixture, 'gradle-and-kotlin'); - const { files: result } = await find( - buildGradle, - [], - ['build.gradle.kts', 'build.gradle'], - new Set([]), - 1, - ); + const { files: result } = await find({ + path: buildGradle, + filter: ['build.gradle.kts', 'build.gradle'], + levelsDeep: 1, + }); const expected = [path.join(buildGradle, 'build.gradle')]; t.same(result.sort(), expected.sort(), 'should return expected file'); }); @@ -199,13 +182,11 @@ test('find build.gradle file in test fixture (ignore build.gradle in the same fo test('find Gemfile.lock file in test fixture (ignore Gemfile in the same folder)', async (t) => { const npmLockfilePath = path.join(testFixture, 'ruby'); - const { files: result } = await find( - npmLockfilePath, - [], - ['Gemfile', 'Gemfile.lock'], - new Set([]), - 1, - ); + const { files: result } = await find({ + path: npmLockfilePath, + filter: ['Gemfile', 'Gemfile.lock'], + levelsDeep: 1, + }); const expected = [path.join(npmLockfilePath, 'Gemfile.lock')]; t.same(result.sort(), expected.sort(), 'should return expected file'); }); @@ -213,26 +194,22 @@ test('find Gemfile.lock file in test fixture (ignore Gemfile in the same folder) test('find yarn.lock file in test fixture (ignore package.json in the same folder)', async (t) => { const yarnLockfilePath = path.join(testFixture, 'yarn'); - const { files: result } = await find( - yarnLockfilePath, - [], - ['package.json', 'yarn.lock'], - new Set([]), - 1, - ); + const { files: result } = await find({ + path: yarnLockfilePath, + filter: ['package.json', 'yarn.lock'], + levelsDeep: 1, + }); const expected = [path.join(yarnLockfilePath, 'yarn.lock')]; t.same(result.sort(), expected.sort(), 'should return expected file'); }); test('find package.json file in test fixture (by default ignoring node_modules)', async (t) => { // four levels deep to ensure node_modules is tested - const { files: result } = await find( - testFixture, - [], - ['package.json'], - new Set([]), - 4, - ); + const { files: result } = await find({ + path: testFixture, + filter: ['package.json'], + levelsDeep: 4, + }); const expected = [ path.join(testFixture, 'npm', 'package.json'), path.join(testFixture, 'npm-with-lockfile', 'package.json'), @@ -242,13 +219,19 @@ test('find package.json file in test fixture (by default ignoring node_modules)' }); test('find Gemfile file in test fixture', async (t) => { - const { files: result } = await find(testFixture, [], ['Gemfile']); + const { files: result } = await find({ + path: testFixture, + filter: ['Gemfile'], + }); const expected = [path.join(testFixture, 'ruby', 'Gemfile')]; t.same(result.sort(), expected.sort(), 'should return expected file'); }); test('find pom.xml files in test fixture', async (t) => { - const { files: result } = await find(testFixture, [], ['pom.xml']); + const { files: result } = await find({ + path: testFixture, + filter: ['pom.xml'], + }); const expected = [ path.join(testFixture, 'maven', 'pom.xml'), path.join(testFixture, 'mvn', 'pom.xml'), @@ -258,7 +241,7 @@ test('find pom.xml files in test fixture', async (t) => { test('find path that does not exist', async (t) => { try { - await find('does-not-exist'); + await find({ path: 'does-not-exist' }); t.fail('expected exception to be thrown'); } catch (err) { t.match( @@ -271,7 +254,7 @@ test('find path that does not exist', async (t) => { test('find path is empty string', async (t) => { try { - await find(''); + await find({ path: '' }); t.fail('expected exception to be thrown'); } catch (err) { t.match(