mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-13 03:13:01 +08:00
201 lines
5.7 KiB
JavaScript
201 lines
5.7 KiB
JavaScript
![]() |
var fs = require('fs');
|
||
|
var path = require('path');
|
||
|
var common = require('./common');
|
||
|
|
||
|
// Buffered file copy, synchronous
|
||
|
// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
|
||
|
// with large files)
|
||
|
function copyFileSync(srcFile, destFile) {
|
||
|
if (!fs.existsSync(srcFile))
|
||
|
common.error('copyFileSync: no such file or directory: ' + srcFile);
|
||
|
|
||
|
var BUF_LENGTH = 64*1024,
|
||
|
buf = new Buffer(BUF_LENGTH),
|
||
|
bytesRead = BUF_LENGTH,
|
||
|
pos = 0,
|
||
|
fdr = null,
|
||
|
fdw = null;
|
||
|
|
||
|
try {
|
||
|
fdr = fs.openSync(srcFile, 'r');
|
||
|
} catch(e) {
|
||
|
common.error('copyFileSync: could not read src file ('+srcFile+')');
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
fdw = fs.openSync(destFile, 'w');
|
||
|
} catch(e) {
|
||
|
common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile);
|
||
|
}
|
||
|
|
||
|
while (bytesRead === BUF_LENGTH) {
|
||
|
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
|
||
|
fs.writeSync(fdw, buf, 0, bytesRead);
|
||
|
pos += bytesRead;
|
||
|
}
|
||
|
|
||
|
fs.closeSync(fdr);
|
||
|
fs.closeSync(fdw);
|
||
|
|
||
|
fs.chmodSync(destFile, fs.statSync(srcFile).mode);
|
||
|
}
|
||
|
|
||
|
// Recursively copies 'sourceDir' into 'destDir'
|
||
|
// Adapted from https://github.com/ryanmcgrath/wrench-js
|
||
|
//
|
||
|
// Copyright (c) 2010 Ryan McGrath
|
||
|
// Copyright (c) 2012 Artur Adib
|
||
|
//
|
||
|
// Licensed under the MIT License
|
||
|
// http://www.opensource.org/licenses/mit-license.php
|
||
|
function cpdirSyncRecursive(sourceDir, destDir, opts) {
|
||
|
if (!opts) opts = {};
|
||
|
|
||
|
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
|
||
|
var checkDir = fs.statSync(sourceDir);
|
||
|
try {
|
||
|
fs.mkdirSync(destDir, checkDir.mode);
|
||
|
} catch (e) {
|
||
|
//if the directory already exists, that's okay
|
||
|
if (e.code !== 'EEXIST') throw e;
|
||
|
}
|
||
|
|
||
|
var files = fs.readdirSync(sourceDir);
|
||
|
|
||
|
for (var i = 0; i < files.length; i++) {
|
||
|
var srcFile = sourceDir + "/" + files[i];
|
||
|
var destFile = destDir + "/" + files[i];
|
||
|
var srcFileStat = fs.lstatSync(srcFile);
|
||
|
|
||
|
if (srcFileStat.isDirectory()) {
|
||
|
/* recursion this thing right on back. */
|
||
|
cpdirSyncRecursive(srcFile, destFile, opts);
|
||
|
} else if (srcFileStat.isSymbolicLink()) {
|
||
|
var symlinkFull = fs.readlinkSync(srcFile);
|
||
|
fs.symlinkSync(symlinkFull, destFile);
|
||
|
} else {
|
||
|
/* At this point, we've hit a file actually worth copying... so copy it on over. */
|
||
|
if (fs.existsSync(destFile) && !opts.force) {
|
||
|
common.log('skipping existing file: ' + files[i]);
|
||
|
} else {
|
||
|
copyFileSync(srcFile, destFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // for files
|
||
|
} // cpdirSyncRecursive
|
||
|
|
||
|
|
||
|
//@
|
||
|
//@ ### cp([options ,] source [,source ...], dest)
|
||
|
//@ ### cp([options ,] source_array, dest)
|
||
|
//@ Available options:
|
||
|
//@
|
||
|
//@ + `-f`: force
|
||
|
//@ + `-r, -R`: recursive
|
||
|
//@
|
||
|
//@ Examples:
|
||
|
//@
|
||
|
//@ ```javascript
|
||
|
//@ cp('file1', 'dir1');
|
||
|
//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
|
||
|
//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
|
||
|
//@ ```
|
||
|
//@
|
||
|
//@ Copies files. The wildcard `*` is accepted.
|
||
|
function _cp(options, sources, dest) {
|
||
|
options = common.parseOptions(options, {
|
||
|
'f': 'force',
|
||
|
'R': 'recursive',
|
||
|
'r': 'recursive'
|
||
|
});
|
||
|
|
||
|
// Get sources, dest
|
||
|
if (arguments.length < 3) {
|
||
|
common.error('missing <source> and/or <dest>');
|
||
|
} else if (arguments.length > 3) {
|
||
|
sources = [].slice.call(arguments, 1, arguments.length - 1);
|
||
|
dest = arguments[arguments.length - 1];
|
||
|
} else if (typeof sources === 'string') {
|
||
|
sources = [sources];
|
||
|
} else if ('length' in sources) {
|
||
|
sources = sources; // no-op for array
|
||
|
} else {
|
||
|
common.error('invalid arguments');
|
||
|
}
|
||
|
|
||
|
var exists = fs.existsSync(dest),
|
||
|
stats = exists && fs.statSync(dest);
|
||
|
|
||
|
// Dest is not existing dir, but multiple sources given
|
||
|
if ((!exists || !stats.isDirectory()) && sources.length > 1)
|
||
|
common.error('dest is not a directory (too many sources)');
|
||
|
|
||
|
// Dest is an existing file, but no -f given
|
||
|
if (exists && stats.isFile() && !options.force)
|
||
|
common.error('dest file already exists: ' + dest);
|
||
|
|
||
|
if (options.recursive) {
|
||
|
// Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*"
|
||
|
// (see Github issue #15)
|
||
|
sources.forEach(function(src, i) {
|
||
|
if (src[src.length - 1] === '/')
|
||
|
sources[i] += '*';
|
||
|
});
|
||
|
|
||
|
// Create dest
|
||
|
try {
|
||
|
fs.mkdirSync(dest, parseInt('0777', 8));
|
||
|
} catch (e) {
|
||
|
// like Unix's cp, keep going even if we can't create dest dir
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sources = common.expand(sources);
|
||
|
|
||
|
sources.forEach(function(src) {
|
||
|
if (!fs.existsSync(src)) {
|
||
|
common.error('no such file or directory: '+src, true);
|
||
|
return; // skip file
|
||
|
}
|
||
|
|
||
|
// If here, src exists
|
||
|
if (fs.statSync(src).isDirectory()) {
|
||
|
if (!options.recursive) {
|
||
|
// Non-Recursive
|
||
|
common.log(src + ' is a directory (not copied)');
|
||
|
} else {
|
||
|
// Recursive
|
||
|
// 'cp /a/source dest' should create 'source' in 'dest'
|
||
|
var newDest = path.join(dest, path.basename(src)),
|
||
|
checkDir = fs.statSync(src);
|
||
|
try {
|
||
|
fs.mkdirSync(newDest, checkDir.mode);
|
||
|
} catch (e) {
|
||
|
//if the directory already exists, that's okay
|
||
|
if (e.code !== 'EEXIST') throw e;
|
||
|
}
|
||
|
|
||
|
cpdirSyncRecursive(src, newDest, {force: options.force});
|
||
|
}
|
||
|
return; // done with dir
|
||
|
}
|
||
|
|
||
|
// If here, src is a file
|
||
|
|
||
|
// When copying to '/path/dir':
|
||
|
// thisDest = '/path/dir/file1'
|
||
|
var thisDest = dest;
|
||
|
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
|
||
|
thisDest = path.normalize(dest + '/' + path.basename(src));
|
||
|
|
||
|
if (fs.existsSync(thisDest) && !options.force) {
|
||
|
common.error('dest file already exists: ' + thisDest, true);
|
||
|
return; // skip file
|
||
|
}
|
||
|
|
||
|
copyFileSync(src, thisDest);
|
||
|
}); // forEach(src)
|
||
|
}
|
||
|
module.exports = _cp;
|