From 3491e2eeeade92229c0b012d6d2138ba11317e5b Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Wed, 5 May 2021 09:40:12 -0400 Subject: [PATCH] Add option to cp to only copy contents of directory (#788) * Add option to not copy source directory * Cleanup * Update condition to be consistent --- packages/io/__tests__/io.test.ts | 23 +++++++++++++++++++++++ packages/io/src/io.ts | 12 +++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/packages/io/__tests__/io.test.ts b/packages/io/__tests__/io.test.ts index eacedd0f..08bf5e67 100644 --- a/packages/io/__tests__/io.test.ts +++ b/packages/io/__tests__/io.test.ts @@ -90,6 +90,29 @@ describe('cp', () => { ) }) + it('copies directory into existing destination with -r without copying source directory', async () => { + const root: string = path.join( + getTestTemp(), + 'cp_with_-r_existing_dest_no_source_dir' + ) + const sourceFolder: string = path.join(root, 'cp_source') + const sourceFile: string = path.join(sourceFolder, 'cp_source_file') + + const targetFolder: string = path.join(root, 'cp_target') + const targetFile: string = path.join(targetFolder, 'cp_source_file') + await io.mkdirP(sourceFolder) + await fs.writeFile(sourceFile, 'test file content', {encoding: 'utf8'}) + await io.mkdirP(targetFolder) + await io.cp(sourceFolder, targetFolder, { + recursive: true, + copySourceDirectory: false + }) + + expect(await fs.readFile(targetFile, {encoding: 'utf8'})).toBe( + 'test file content' + ) + }) + it('copies directory into non-existing destination with -r', async () => { const root: string = path.join(getTestTemp(), 'cp_with_-r_nonexistent_dest') const sourceFolder: string = path.join(root, 'cp_source') diff --git a/packages/io/src/io.ts b/packages/io/src/io.ts index c5602d40..e75e14f7 100644 --- a/packages/io/src/io.ts +++ b/packages/io/src/io.ts @@ -14,6 +14,8 @@ export interface CopyOptions { recursive?: boolean /** Optional. Whether to overwrite existing files in the destination. Defaults to true */ force?: boolean + /** Optional. Whether to copy the source directory along with all the files. Only takes effect when recursive=true and copying a directory. Default is true*/ + copySourceDirectory?: boolean } /** @@ -37,7 +39,7 @@ export async function cp( dest: string, options: CopyOptions = {} ): Promise { - const {force, recursive} = readCopyOptions(options) + const {force, recursive, copySourceDirectory} = readCopyOptions(options) const destStat = (await ioUtil.exists(dest)) ? await ioUtil.stat(dest) : null // Dest is an existing file, but not forcing @@ -47,7 +49,7 @@ export async function cp( // If dest is an existing directory, should copy inside. const newDest: string = - destStat && destStat.isDirectory() + destStat && destStat.isDirectory() && copySourceDirectory ? path.join(dest, path.basename(source)) : dest @@ -278,7 +280,11 @@ export async function findInPath(tool: string): Promise { function readCopyOptions(options: CopyOptions): Required { const force = options.force == null ? true : options.force const recursive = Boolean(options.recursive) - return {force, recursive} + const copySourceDirectory = + options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory) + return {force, recursive, copySourceDirectory} } async function cpDirRecursive(