Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #53: Overwrite readonly #57

Merged
merged 3 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ Options:
-c, --command <command> A command text to transform each file.
-C, --clean Clean files that matches <source> like pattern in
<dest> directory before the first copying.
-i --ignore A comma separated list of gitignore style ignore
-f, --force Force the file to be copied, even if the
destination is readonly.
-i, --ignore A comma separated list of gitignore style ignore
patterns.
-L, --dereference Follow symbolic links when copying from them.
-h, --help Print usage information.
Expand Down Expand Up @@ -109,6 +111,7 @@ cpx.copy(source, dest, callback)
- **options.dereference** `{boolean}` -- The flag to follow symbolic links when copying from them. Default: `false`.
- **options.includeEmptyDirs** `{boolean}` -- The flag to copy empty directories which is matched with the glob. Default: `false`.
- **options.initialCopy** `{boolean}` -- The flag to not copy at the initial time of watch. This is for `cpx.watch()`. Default: `true`.
- **options.force** `{boolean}` -- The flag to copy file to the destination, even if it is readonly.
- **options.preserve** `{boolean}` -- The flag to copy uid, gid, atime, and mtime of files. Default: `false`.
- **options.transform** `{((filepath: string) => stream.Transform)[]}` -- Functions that creates a `stream.Transform` object to transform each copying file.
- **options.update** `{boolean}` -- The flag to not overwrite files on destination if the source file is older. Default: `false`.
Expand Down
4 changes: 3 additions & 1 deletion bin/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ Options:
-c, --command <command> A command text to transform each file.
-C, --clean Clean files that matches <source> like pattern in
<dest> directory before the first copying.
-i --ignore A comma separated list of gitignore style ignore
-f, --force Force the file to be copied, even if the
destination is readonly.
-i, --ignore A comma separated list of gitignore style ignore
patterns.
-L, --dereference Follow symbolic links when copying from them.
-h, --help Print usage information.
Expand Down
2 changes: 2 additions & 0 deletions bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const args = subarg(process.argv.slice(2), {
alias: {
c: "command",
C: "clean",
f: "force",
h: "help",
includeEmptyDirs: "include-empty-dirs",
i: "ignore",
Expand All @@ -37,6 +38,7 @@ const args = subarg(process.argv.slice(2), {
"clean",
"dereference",
"help",
"force",
"include-empty-dirs",
"initial",
"preserve",
Expand Down
1 change: 1 addition & 0 deletions bin/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ module.exports = function main(source, outDir, args) {
dereference: args.dereference,
includeEmptyDirs: args.includeEmptyDirs,
initialCopy: args.initial,
force: args.force,
preserve: args.preserve,
update: args.update,
ignore: args.ignore && args.ignore.split(","),
Expand Down
1 change: 1 addition & 0 deletions lib/copy-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const removeFileSync = require("./utils/remove-file-sync")
* @param {boolean} [options.dereference=false] The flag to dereference symbolic links.
* @param {boolean} [options.includeEmptyDirs=false] The flag to copy empty directories.
* @param {boolean} [options.initialCopy=true] The flag to copy files at the first time.
* @param {boolean} [options.force=false] The flag to copy file to the destination, even if it is readonly.
* @param {boolean} [options.preserve=false] The flag to copy file attributes such as timestamps, users, and groups.
* @param {boolean} [options.update=false] The flag to not overwrite newer files.
* @param {string|Array.<string>} [options.ignore] - gitignore string or array of gitignore strings
Expand Down
1 change: 1 addition & 0 deletions lib/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const removeFile = require("./utils/remove-file")
* @param {boolean} [options.dereference=false] The flag to dereference symbolic links.
* @param {boolean} [options.includeEmptyDirs=false] The flag to copy empty directories.
* @param {boolean} [options.initialCopy=true] The flag to copy files at the first time.
* @param {boolean} [options.force=false] The flag to copy file to the destination, even if it is readonly.
* @param {boolean} [options.preserve=false] The flag to copy file attributes such as timestamps, users, and groups.
* @param {(function(string):void)[]} [options.transform] The array of the factories of transform streams.
* @param {boolean} [options.update=false] The flag to not overwrite newer files.
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/copy-file-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ module.exports = function copyFileSync(source, output, options) {
fs.ensureDirSync(output)
} else {
fs.ensureDirSync(path.dirname(output))

if (!(stat.mode & 0o200) && options.force) {
try {
await fs.chmod(output, stat.mode | 0o200);
} catch (dstChmodError) {
if (dstChmodError.code !== "ENOENT") {
throw dstChmodError
}
}
}
fs.copySync(source, output)
}
fs.chmodSync(output, stat.mode)
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/copy-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ module.exports = async function copyFile(source, output, options) {
await fs.ensureDir(output)
} else {
await fs.ensureDir(path.dirname(output))

if (!(stat.mode & 0o200) && options.force) {
try {
await fs.chmod(output, stat.mode | 0o200);
} catch (dstChmodError) {
if (dstChmodError.code !== "ENOENT") {
throw dstChmodError
}
}
}
await copyFileContent(source, output, options.transform)
}
await fs.chmod(output, stat.mode)
Expand Down
4 changes: 3 additions & 1 deletion lib/utils/normalize-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ function getBasePath(source) {
* @param {boolean} [options.dereference=false] The flag to dereference symbolic links.
* @param {boolean} [options.includeEmptyDirs=false] The flag to copy empty directories.
* @param {boolean} [options.initialCopy=true] The flag to copy files at the first time.
* @param {boolean} [options.force=false] The flag force overwrite the destination, even if it is readonly.
* @param {boolean} [options.preserve=false] The flag to copy file attributes such as timestamps, users, and groups.
* @param {(function(string):stream.Transform)[]} [options.transform=null] The array of transform function's factories.
* @param {boolean} [options.update=false] The flag to not overwrite newer files.
* @param {string|Array.<string>} [options.ignore] - gitignore string or array of gitignore strings
* @returns {{baseDir:string,clean:boolean,dereference:boolean,includeEmptyDirs:boolean,initialCopy:boolean,outputDir:string,preserve:boolean,source:string,transform:any[],toDestination:any,update:boolean,ignore:string|Array.<string>}} The normalized options.
* @returns {{baseDir:string,clean:boolean,dereference:boolean,includeEmptyDirs:boolean,initialCopy:boolean,outputDir:string,force:boolean,preserve:boolean,source:string,transform:any[],toDestination:any,update:boolean,ignore:string|Array.<string>}} The normalized options.
* @private
*/
module.exports = function normalizeOptions(source, outputDir, options) {
Expand All @@ -65,6 +66,7 @@ module.exports = function normalizeOptions(source, outputDir, options) {
includeEmptyDirs: Boolean(options && options.includeEmptyDirs),
initialCopy: (options && options.initialCopy) !== false,
outputDir,
force: Boolean(options && options.force),
preserve: Boolean(options && options.preserve),
source: normalizedSource,
toDestination,
Expand Down
2 changes: 2 additions & 0 deletions lib/utils/watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ module.exports = class Watcher extends EventEmitter {
* @param {boolean} options.includeEmptyDirs The flag to copy empty directories.
* @param {boolean} options.initialCopy The flag to copy files at the first time.
* @param {string} options.outputDir The path to the output directory.
* @param {boolean} options.force The flag to overwrite the destination, even if it is readonly.
* @param {boolean} options.preserve The flag to copy file attributes such as timestamps, users, and groups.
* @param {string} options.source The glob pattern of source files.
* @param {(function(string):stream.Transform)[]} options.transform The array of transform function's factories.
Expand All @@ -111,6 +112,7 @@ module.exports = class Watcher extends EventEmitter {
this.matcher = new Minimatch(options.source)
this.ignore = ignore({ allowRelativePaths: true }).add(options.ignore)
this.outputDir = options.outputDir
this.force = options.force
this.preserve = options.preserve
this.source = options.source
this.toDestination = options.toDestination
Expand Down
1 change: 1 addition & 0 deletions lib/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const Watcher = require("./utils/watcher")
* @param {boolean} [options.dereference=false] The flag to dereference symbolic links.
* @param {boolean} [options.includeEmptyDirs=false] The flag to copy empty directories.
* @param {boolean} [options.initialCopy=true] The flag to copy files at the first time.
* @param {boolean} [options.force=false] The flag to copy file to the destination, even if it is readonly..
* @param {boolean} [options.preserve=false] The flag to copy file attributes such as timestamps, users, and groups.
* @param {(function(string):void)[]} [options.transform] The array of the factories of transform streams.
* @param {boolean} [options.update=false] The flag to not overwrite newer files.
Expand Down