From 15e44b06407b9106f92f1185c75dd5fa7b7fb52a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 9 Feb 2025 00:19:22 +0100 Subject: [PATCH] cli/new: further templaing simplification, avoid tmpdir Signed-off-by: Patrik Oldsberg --- .../execution/TemporaryDirectoryManager.ts | 42 --------------- .../execution/executePluginPackageTemplate.ts | 51 +++++++------------ 2 files changed, 18 insertions(+), 75 deletions(-) delete mode 100644 packages/cli/src/lib/new/execution/TemporaryDirectoryManager.ts diff --git a/packages/cli/src/lib/new/execution/TemporaryDirectoryManager.ts b/packages/cli/src/lib/new/execution/TemporaryDirectoryManager.ts deleted file mode 100644 index 491c90db4b..0000000000 --- a/packages/cli/src/lib/new/execution/TemporaryDirectoryManager.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2025 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import os from 'os'; -import fs from 'fs-extra'; -import { join as joinPath } from 'path'; - -export class TemporaryDirectoryManager { - #dirs = new Array(); - - static create() { - const manager = new TemporaryDirectoryManager(); - process.on('beforeExit', manager.cleanup); - return manager; - } - - private constructor() {} - - createDir = async (name: string): Promise => { - const dir = await fs.mkdtemp(joinPath(os.tmpdir(), name)); - this.#dirs.push(dir); - return dir; - }; - - cleanup = () => { - for (const dir of this.#dirs) { - fs.rmSync(dir, { recursive: true, force: true, maxRetries: 10 }); - } - }; -} diff --git a/packages/cli/src/lib/new/execution/executePluginPackageTemplate.ts b/packages/cli/src/lib/new/execution/executePluginPackageTemplate.ts index 30f0de1488..d9541280ed 100644 --- a/packages/cli/src/lib/new/execution/executePluginPackageTemplate.ts +++ b/packages/cli/src/lib/new/execution/executePluginPackageTemplate.ts @@ -15,17 +15,11 @@ */ import fs from 'fs-extra'; -import chalk from 'chalk'; -import { - dirname, - resolve as resolvePath, - relative as relativePath, -} from 'path'; +import { dirname, resolve as resolvePath } from 'path'; import { paths } from '../../paths'; import { PortableTemplate, PortableTemplateInput } from '../types'; -import { ForwardedError } from '@backstage/errors'; -import { TemporaryDirectoryManager } from './TemporaryDirectoryManager'; +import { ForwardedError, InputError } from '@backstage/errors'; import { isMonoRepo as getIsMonoRepo } from '@backstage/cli-node'; import { PortableTemplater } from './PortableTemplater'; @@ -35,19 +29,13 @@ export async function executePluginPackageTemplate( ): Promise<{ targetDir: string }> { const targetDir = paths.resolveTargetRoot(input.packageParams.packagePath); - const shortPluginDir = relativePath(paths.targetRoot, targetDir); if (await fs.pathExists(targetDir)) { - throw new Error( - `A package with the same plugin ID already exists at ${chalk.cyan( - shortPluginDir, - )}. Please try again with a different ID.`, + throw new InputError( + `Package '${input.packageParams.packagePath}' already exists`, ); } - const tmpDirManager = TemporaryDirectoryManager.create(); - try { - const tempDir = await tmpDirManager.createDir('backstage-create'); const isMonoRepo = await getIsMonoRepo(); const templater = await PortableTemplater.create({ @@ -60,34 +48,31 @@ export async function executePluginPackageTemplate( continue; } - const destPath = resolvePath(tempDir, file.path); + const destPath = resolvePath(targetDir, file.path); await fs.ensureDir(dirname(destPath)); - const content = + let content = file.syntax === 'handlebars' ? templater.template(file.content) : file.content; + // Try to format JSON files + if (file.path.endsWith('.json')) { + try { + content = JSON.stringify(JSON.parse(content), null, 2); + } catch { + /* ignore */ + } + } + await fs.writeFile(destPath, content).catch(error => { throw new ForwardedError(`Failed to copy file to ${destPath}`, error); }); } - // Format package.json if it exists - const pkgJsonPath = resolvePath(tempDir, 'package.json'); - if (await fs.pathExists(pkgJsonPath)) { - const pkgJson = await fs.readJson(pkgJsonPath); - await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 }); - } - - await fs.move(tempDir, targetDir).catch(error => { - throw new Error( - `Failed to move package from ${tempDir} to ${targetDir}, ${error.message}`, - ); - }); - return { targetDir }; - } finally { - tmpDirManager.cleanup(); + } catch (error) { + await fs.rm(targetDir, { recursive: true, force: true, maxRetries: 10 }); + throw error; } }