diff --git a/src/cli/services/path.service.spec.ts b/src/cli/services/path.service.spec.ts index 46047a84ef..f74d8a107c 100644 --- a/src/cli/services/path.service.spec.ts +++ b/src/cli/services/path.service.spec.ts @@ -243,6 +243,22 @@ describe('cli/services/path.service', () => { expect(await pathSvc.createDir(dir)).toBeUndefined(); }); + test('createDir: throws when the path is no folder', async () => { + const dir = rootPath('env123/dir'); + const link = rootPath('env123/link'); + const file = rootPath('env123/file'); + await pathSvc.createDir(dir); + await fs.symlink(dir, link); + await writeFile(file, ''); + + await expect(pathSvc.createDir(link)).rejects.toThrow( + `Path exists and is not a directory: ${link}`, + ); + await expect(pathSvc.createDir(file)).rejects.toThrow( + `Path exists and is not a directory: ${file}`, + ); + }); + test('toolInit', async () => { expect(pathSvc.toolInitPath('node')).toBe( rootPath('tmp/containerbase/tool.init.d/node'), diff --git a/src/cli/services/path.service.ts b/src/cli/services/path.service.ts index 8909843c10..033bf48c62 100644 --- a/src/cli/services/path.service.ts +++ b/src/cli/services/path.service.ts @@ -112,11 +112,17 @@ export class PathService { /** * Creates a folder and its missing parents, owned by the configured user. * An existing folder is left as is. + * + * @throws when the path exists but is no folder, eg. a symlink or a file */ async createDir(path: string, mode = 0o775): Promise { - if (await pathExists(path)) { + const stats = await fs.lstat(path).catch(() => null); + if (stats?.isDirectory()) { return; } + if (stats) { + throw new Error(`Path exists and is not a directory: ${path}`); + } const parent = dirname(path); if (!(await pathExists(parent))) { await this.createDir(parent, 0o775);