Skip to content

Commit 131b88f

Browse files
authored
Fix cp from readonly source (shelljs#870)
This is a redo of PR shelljs#555. This rebases, cleans up a test, and fixes a bug (the original PR uses `fs.chown()` instead of `fs.chownSync()`). Fixes shelljs#98
1 parent 1dd437e commit 131b88f

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

src/cp.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ function cpdirSyncRecursive(sourceDir, destDir, currentDepth, opts) {
9999
// Create the directory where all our junk is moving to; read the mode of the
100100
// source directory and mirror it
101101
try {
102-
var checkDir = common.statFollowLinks(sourceDir);
103-
fs.mkdirSync(destDir, checkDir.mode);
102+
fs.mkdirSync(destDir);
104103
} catch (e) {
105104
// if the directory already exists, that's okay
106105
if (e.code !== 'EEXIST') throw e;
@@ -151,6 +150,11 @@ function cpdirSyncRecursive(sourceDir, destDir, currentDepth, opts) {
151150
}
152151
}
153152
} // for files
153+
154+
// finally change the mode for the newly created directory (otherwise, we
155+
// couldn't add files to a read-only directory).
156+
var checkDir = common.statFollowLinks(sourceDir);
157+
fs.chmodSync(destDir, checkDir.mode);
154158
} // cpdirSyncRecursive
155159

156160
// Checks if cureent file was created recently

test/cp.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,3 +756,27 @@ test('should not overwrite recently created files (not give error no-force mode)
756756
// Ensure First file is copied
757757
t.is(shell.cat(`${t.context.tmp}/file1`).toString(), 'test1');
758758
});
759+
760+
// cp -R should be able to copy a readonly src (issue #98).
761+
// On Windows, chmod acts VERY differently so skip these tests for now
762+
test('cp -R should be able to copy a readonly src. issue #98; (Non window platforms only)', t => {
763+
utils.skipOnWin(t, () => {
764+
shell.cp('-r', 'test/resources/cp', t.context.tmp);
765+
shell.chmod('555', `${t.context.tmp}/cp/`);
766+
shell.chmod('555', `${t.context.tmp}/cp/dir_a`);
767+
shell.chmod('555', `${t.context.tmp}/cp/dir_b`);
768+
shell.chmod('555', `${t.context.tmp}/cp/a`);
769+
770+
const result = shell.cp('-r', `${t.context.tmp}/cp`, `${t.context.tmp}/cp_cp`);
771+
t.falsy(shell.error());
772+
t.falsy(result.stderr);
773+
t.is(result.code, 0);
774+
775+
t.is(shell.ls('-R', `${t.context.tmp}/cp`) + '', shell.ls('-R', `${t.context.tmp}/cp_cp`) + '');
776+
t.is(fs.statSync(`${t.context.tmp}/cp_cp`).mode & parseInt('777', 8), parseInt('555', 8));
777+
t.is(fs.statSync(`${t.context.tmp}/cp_cp/dir_a`).mode & parseInt('777', 8), parseInt('555', 8));
778+
t.is(fs.statSync(`${t.context.tmp}/cp_cp/a`).mode & parseInt('777', 8), parseInt('555', 8));
779+
780+
shell.chmod('-R', '755', t.context.tmp);
781+
});
782+
});

0 commit comments

Comments
 (0)