/platforms/browser/cordova/node_modules/shelljs/src/cp.js
JavaScript | 210 lines | 90 code | 20 blank | 100 comment | 32 complexity | e7ee71ccc7b4022dc088d74d74f0553b MD5 | raw file
- var fs = require('fs');
- var path = require('path');
- var common = require('./common');
- var os = require('os');
- // 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, os.platform() === "win32" ? "junction" : null);
- } else {
- /* At this point, we've hit a file actually worth copying... so copy it on over. */
- if (fs.existsSync(destFile) && opts.no_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 (default behavior)
- //@ + `-n`: no-clobber
- //@ + `-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': '!no_force',
- 'n': 'no_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.no_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] += '*';
- // If src is a directory and dest doesn't exist, 'cp -r src dest' should copy src/* into dest
- } else if (fs.statSync(src).isDirectory() && !exists) {
- 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') {
- common.error('dest file no such file or directory: ' + newDest, true);
- throw e;
- }
- }
- cpdirSyncRecursive(src, newDest, {no_force: options.no_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.no_force) {
- common.error('dest file already exists: ' + thisDest, true);
- return; // skip file
- }
- copyFileSync(src, thisDest);
- }); // forEach(src)
- }
- module.exports = _cp;