Skip to content

Commit 6b2226b

Browse files
authored
Fix rename failing when destination is the same folder as origin (#122)
1 parent 55b2758 commit 6b2226b

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

index.js

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ const expandPatternsWithBraceExpansion = patterns => patterns.flatMap(pattern =>
7676
*/
7777
const isSelfCopy = (from, to) => path.resolve(to) === path.resolve(from);
7878

79-
const ensureNotSelfCopy = (from, to) => {
80-
if (isSelfCopy(from, to)) {
81-
throw new CpyError(`Refusing to copy to itself: \`${from}\``);
82-
}
83-
84-
return to;
85-
};
86-
8779
const relativizeWithin = (base, file) => {
8880
const relativePath = path.relative(base, file);
8981
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
@@ -125,7 +117,7 @@ const computeToForGlob = ({entry, destination, options}) => {
125117

126118
const computeToForNonGlob = ({entry, destination, options}) => {
127119
if (path.isAbsolute(destination)) {
128-
return ensureNotSelfCopy(entry.path, path.join(destination, entry.name));
120+
return path.join(destination, entry.name);
129121
}
130122

131123
const insideCwd = !path.relative(options.cwd, entry.path).startsWith('..');
@@ -145,10 +137,10 @@ const computeToForNonGlob = ({entry, destination, options}) => {
145137
}
146138

147139
if (!entry.pattern.isDirectory && !insideCwd) {
148-
return ensureNotSelfCopy(entry.path, path.join(path.resolve(options.cwd, destination), entry.name));
140+
return path.join(path.resolve(options.cwd, destination), entry.name);
149141
}
150142

151-
return ensureNotSelfCopy(entry.path, path.join(options.cwd, destination, path.relative(options.cwd, entry.path)));
143+
return path.join(options.cwd, destination, path.relative(options.cwd, entry.path));
152144
};
153145

154146
const preprocessDestinationPath = ({entry, destination, options}) => (
@@ -334,14 +326,19 @@ export default function cpy(
334326
return pMap(
335327
entries,
336328
async entry => {
337-
const to = renameFile(
338-
preprocessDestinationPath({
339-
entry,
340-
destination,
341-
options,
342-
}),
343-
options.rename,
344-
);
329+
let to = preprocessDestinationPath({
330+
entry,
331+
destination,
332+
options,
333+
});
334+
335+
// Apply rename after computing the base destination path
336+
to = renameFile(to, options.rename);
337+
338+
// Check for self-copy after rename has been applied
339+
if (isSelfCopy(entry.path, to)) {
340+
throw new CpyError(`Refusing to copy to itself: \`${entry.path}\``);
341+
}
345342

346343
try {
347344
await copyFile(entry.path, to, {...options, onProgress: fileProgressHandler});

test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,19 @@ test('rename function receives the basename argument with the file extension', a
370370
t.true(visited.includes('foo.ts'));
371371
});
372372

373+
test('rename at the same directory', async t => {
374+
fs.mkdirSync(t.context.tmp);
375+
fs.mkdirSync(path.join(t.context.tmp, 'dest'));
376+
fs.writeFileSync(path.join(t.context.tmp, 'hello.js'), 'console.log("hello");');
377+
378+
await cpy(['hello.js'], './', {
379+
cwd: t.context.tmp,
380+
rename: 'file-renamed.js',
381+
});
382+
383+
t.is(read(t.context.tmp, 'file-renamed.js'), 'console.log("hello");');
384+
});
385+
373386
test('flatten directory tree', async t => {
374387
fs.mkdirSync(t.context.tmp);
375388
fs.mkdirSync(path.join(t.context.tmp, 'source'));

0 commit comments

Comments
 (0)