From 0674095ea3d717ec685fde1103da14c7da7690e6 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 31 Aug 2022 11:22:31 +0200 Subject: [PATCH] chore: remove the `existsSync` with an async filter Signed-off-by: blam --- .../lib/files/serializeDirectoryContents.ts | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts index 0c389969b9..1197db000a 100644 --- a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts +++ b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts @@ -14,11 +14,12 @@ * limitations under the License. */ -import { promises as fs, existsSync } from 'fs'; +import { promises as fs } from 'fs'; import globby from 'globby'; import limiterFactory from 'p-limit'; import { resolveSafeChildPath } from '@backstage/backend-common'; import { SerializedFile } from './types'; +import { isError } from '@backstage/errors'; const DEFAULT_GLOB_PATTERNS = ['./**', '!.git']; @@ -32,6 +33,14 @@ export const isExecutable = (fileMode: number | undefined) => { return res > 0; }; +async function asyncFilter( + array: T[], + callback: (value: T, index: number, array: T[]) => Promise, +): Promise { + const filterMap = await Promise.all(array.map(callback)); + return array.filter((_value, index) => filterMap[index]); +} + export async function serializeDirectoryContents( sourcePath: string, options?: { @@ -53,26 +62,33 @@ export async function serializeDirectoryContents( const limiter = limiterFactory(10); + const valid = await asyncFilter(paths, async ({ dirent, path }) => { + if (dirent.isDirectory()) return false; + if (!dirent.isSymbolicLink()) return true; + + const safePath = resolveSafeChildPath(sourcePath, path); + + // we only want files that don't exist + try { + await fs.stat(safePath); + return false; + } catch (e) { + return isError(e) && e.code === 'ENOENT'; + } + }); + return Promise.all( - paths - .filter(({ dirent }) => !dirent.isDirectory()) - .filter(({ dirent, path }) => { - if (!dirent.isSymbolicLink()) return true; - const safePath = resolveSafeChildPath(sourcePath, path); - if (!existsSync(safePath)) return true; // We only want symlinks that DO NOT exist (yet) - return false; - }) - .map(async ({ dirent, path, stats }) => ({ - path, - content: await limiter(async () => { - const absFilePath = resolveSafeChildPath(sourcePath, path); - if (dirent.isSymbolicLink()) { - return fs.readlink(absFilePath, 'buffer'); - } - return fs.readFile(absFilePath); - }), - executable: isExecutable(stats?.mode), - symlink: dirent.isSymbolicLink(), - })), + valid.map(async ({ dirent, path, stats }) => ({ + path, + content: await limiter(async () => { + const absFilePath = resolveSafeChildPath(sourcePath, path); + if (dirent.isSymbolicLink()) { + return fs.readlink(absFilePath, 'buffer'); + } + return fs.readFile(absFilePath); + }), + executable: isExecutable(stats?.mode), + symlink: dirent.isSymbolicLink(), + })), ); }