Skip to content

Commit 8dce55f

Browse files
authored
breaking: replace shelljs with fs-extra (#851)
* breaking: replace shell.rm with fs.removeSync * breaking: replace shell.mkdir w/ fs.ensureDirSync * breaking: replace shelljs.which w/ which * breaking: replace shelljs.cp w/ fs.copySync * breaking: replace shell.mv w/ fs.moveSync * breaking: replace shell.sed w/ utils.replaceFileContents * breaking: replace shell.echo w/ events.emit * breaking: remove shell.chmod & shell.find usage * breaking: replace shell.test w/ fs.existsSync * breaking: replace shell.ls w/ fs.readdirSync * breaking: replace shell.grep w/ utils.grep * chore: applied lint fixes from shelljs removal changes * breaking(test): drop shell.exec in killsim * Replace pgrep command with find-process * Replace shell.exec with superspawn.spawn * breaking: replace shell.exec w/ superspawn in create.spec.js * breaking: remove shell.config * breaking: replace more shell.cp w/ fs.copySync * Added missing defaults.xml test fixture file * breaking: final remove of shelljs * chore: update package-lock * chore: use verbose emit
1 parent 67bea75 commit 8dce55f

22 files changed

+444
-356
lines changed

LICENSE

-30
Original file line numberDiff line numberDiff line change
@@ -224,33 +224,3 @@ CordovaLib/classes/NSData+Base64.*
224224
// misrepresented as being the original software.
225225
// 3. This notice may not be removed or altered from any source
226226
// distribution.
227-
228-
================================================================================
229-
bin/node_modules/shelljs:
230-
================================================================================
231-
Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
232-
All rights reserved.
233-
234-
You may use this project under the terms of the New BSD license as follows:
235-
236-
Redistribution and use in source and binary forms, with or without
237-
modification, are permitted provided that the following conditions are met:
238-
* Redistributions of source code must retain the above copyright
239-
notice, this list of conditions and the following disclaimer.
240-
* Redistributions in binary form must reproduce the above copyright
241-
notice, this list of conditions and the following disclaimer in the
242-
documentation and/or other materials provided with the distribution.
243-
* Neither the name of Artur Adib nor the
244-
names of the contributors may be used to endorse or promote products
245-
derived from this software without specific prior written permission.
246-
247-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
248-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
250-
ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY
251-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
252-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
253-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
254-
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
256-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

bin/lib/create.js

+77-77
Large diffs are not rendered by default.

bin/lib/utils.js

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
*/
19+
20+
/*
21+
Provides a set of utility methods, which can also be spied on during unit tests.
22+
*/
23+
24+
// TODO: Perhaps this should live in cordova-common?
25+
26+
const fs = require('fs-extra');
27+
const { events } = require('cordova-common');
28+
29+
/**
30+
* Reads, searches, and replaces the found occurences with replacementString and then writes the file back out.
31+
* A backup is not made.
32+
*
33+
* @param {string} file A file path to a readable & writable file
34+
* @param {RegExp} searchRegex The search regex
35+
* @param {string} replacementString The string to replace the found occurences
36+
* @returns {void}
37+
*/
38+
exports.replaceFileContents = function (file, searchRegex, replacementString) {
39+
let contents;
40+
try {
41+
contents = fs.readFileSync(file).toString();
42+
} catch (ex) {
43+
events.emit('verbose', `Trying to read file: ${file}`);
44+
throw ex;
45+
}
46+
contents = contents.replace(searchRegex, replacementString);
47+
fs.writeFileSync(file, contents);
48+
};
49+
50+
/**
51+
* Reads a file and scans for regex. Returns the line of the first occurence or null if no occurences are found.
52+
*
53+
* @param {string} file A file path
54+
* @param {RegExp} regex A search regex
55+
* @returns string|null
56+
*/
57+
exports.grep = function (file, regex) {
58+
const contents = fs.readFileSync(file).toString().replace(/\\r/g, '').split('\n');
59+
for (let i = 0; i < contents.length; i++) {
60+
const line = contents[i];
61+
if (regex.test(line)) {
62+
return line;
63+
}
64+
}
65+
return null;
66+
};

bin/templates/scripts/cordova/lib/build.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
const Q = require('q');
2121
const path = require('path');
22-
const shell = require('shelljs');
22+
const which = require('which');
2323
const superspawn = require('cordova-common').superspawn;
2424
const fs = require('fs-extra');
2525
const plist = require('plist');
@@ -222,7 +222,7 @@ module.exports.run = buildOpts => {
222222
const buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator'));
223223

224224
// remove the build/device folder before building
225-
shell.rm('-rf', buildOutputDir);
225+
fs.removeSync(buildOutputDir);
226226

227227
const xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget, buildOpts.automaticProvisioning);
228228
return superspawn.spawn('xcodebuild', xcodebuildArgs, { cwd: projectPath, printCommand: true, stdio: 'inherit' });
@@ -262,7 +262,7 @@ module.exports.run = buildOpts => {
262262
const buildOutputDir = path.join(projectPath, 'build', 'device');
263263

264264
function checkSystemRuby () {
265-
const ruby_cmd = shell.which('ruby');
265+
const ruby_cmd = which.sync('ruby', { nothrow: true });
266266

267267
if (ruby_cmd !== '/usr/bin/ruby') {
268268
events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' +
@@ -289,7 +289,7 @@ module.exports.run = buildOpts => {
289289
*/
290290
function findXCodeProjectIn (projectPath) {
291291
// 'Searching for Xcode project in ' + projectPath);
292-
const xcodeProjFiles = shell.ls(projectPath).filter(name => path.extname(name) === '.xcodeproj');
292+
const xcodeProjFiles = fs.readdirSync(projectPath).filter(name => path.extname(name) === '.xcodeproj');
293293

294294
if (xcodeProjFiles.length === 0) {
295295
return Q.reject(`No Xcode project found in ${projectPath}`);

bin/templates/scripts/cordova/lib/check_reqs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
'use strict';
2121

2222
const Q = require('q');
23-
const shell = require('shelljs');
23+
const which = require('which');
2424
const versions = require('./versions');
2525

2626
const SUPPORTED_OS_PLATFORMS = ['darwin'];
@@ -83,7 +83,7 @@ function checkTool (tool, minVersion, message, toolFriendlyName) {
8383
toolFriendlyName = toolFriendlyName || tool;
8484

8585
// Check whether tool command is available at all
86-
const tool_command = shell.which(tool);
86+
const tool_command = which.sync(tool, { nothrow: true });
8787
if (!tool_command) {
8888
return Q.reject(`${toolFriendlyName} was not found. ${message || ''}`);
8989
}

bin/templates/scripts/cordova/lib/clean.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919

2020
const Q = require('q');
2121
const path = require('path');
22-
const shell = require('shelljs');
22+
const fs = require('fs-extra');
2323
const superspawn = require('cordova-common').superspawn;
2424

2525
const projectPath = path.join(__dirname, '..', '..');
2626

2727
module.exports.run = () => {
28-
const projectName = shell.ls(projectPath).filter(name => path.extname(name) === '.xcodeproj')[0];
28+
const projectName = fs.readdirSync(projectPath).filter(name => path.extname(name) === '.xcodeproj');
2929

3030
if (!projectName) {
3131
return Q.reject(`No Xcode project found in ${projectPath}`);
@@ -41,5 +41,5 @@ module.exports.run = () => {
4141

4242
return xcodebuildClean('Debug')
4343
.then(() => xcodebuildClean('Release'))
44-
.then(() => shell.rm('-rf', path.join(projectPath, 'build')));
44+
.then(() => fs.removeSync(path.join(projectPath, 'build')));
4545
};

bin/templates/scripts/cordova/lib/plugman/pluginHandlers.js

+11-15
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
'use strict';
1818
const fs = require('fs-extra');
1919
const path = require('path');
20-
const shell = require('shelljs');
2120
const util = require('util');
2221
const events = require('cordova-common').events;
2322
const CordovaError = require('cordova-common').CordovaError;
@@ -77,7 +76,7 @@ const handlers = {
7776
const destFile = path.resolve(project.resources_dir, target);
7877

7978
project.xcode.removeResourceFile(path.join('Resources', target));
80-
shell.rm('-rf', destFile);
79+
fs.removeSync(destFile);
8180
}
8281
},
8382
framework: { // CB-5238 custom frameworks only
@@ -149,7 +148,7 @@ const handlers = {
149148
if (pbxFile) {
150149
project.xcode.removeFromPbxEmbedFrameworksBuildPhase(pbxFile);
151150
}
152-
shell.rm('-rf', targetDir);
151+
fs.removeSync(targetDir);
153152
}
154153
},
155154
'lib-file': {
@@ -201,11 +200,11 @@ const handlers = {
201200
scriptContent = `cordova.define("${moduleName}", function(require, exports, module) {\n${scriptContent}\n});\n`;
202201

203202
const moduleDestination = path.resolve(project.www, 'plugins', plugin.id, obj.src);
204-
shell.mkdir('-p', path.dirname(moduleDestination));
203+
fs.ensureDirSync(path.dirname(moduleDestination));
205204
fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
206205
if (options && options.usePlatformWww) {
207206
const platformWwwDestination = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
208-
shell.mkdir('-p', path.dirname(platformWwwDestination));
207+
fs.ensureDirSync(path.dirname(platformWwwDestination));
209208
fs.writeFileSync(platformWwwDestination, scriptContent, 'utf-8');
210209
}
211210
},
@@ -287,7 +286,7 @@ function uninstallHelper (type, obj, project_dir, plugin_id, options, project) {
287286
project_ref = `Plugins/${fixPathSep(path.relative(project.plugins_dir, destFile))}`;
288287
}
289288

290-
shell.rm('-rf', targetDir);
289+
fs.removeSync(targetDir);
291290

292291
if (type === 'header-file') {
293292
project.xcode.removeHeaderFile(project_ref);
@@ -319,15 +318,12 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
319318
// check that dest path is located in project directory
320319
if (dest.indexOf(project_dir) !== 0) { throw new CordovaError(`Destination "${dest}" for source file "${src}" is located outside the project`); }
321320

322-
shell.mkdir('-p', path.dirname(dest));
321+
fs.ensureDirSync(path.dirname(dest));
323322

324323
if (link) {
325324
linkFileOrDirTree(src, dest);
326-
} else if (fs.statSync(src).isDirectory()) {
327-
// XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
328-
shell.cp('-Rf', path.join(src, '/*'), dest);
329325
} else {
330-
shell.cp('-f', src, dest);
326+
fs.copySync(src, dest);
331327
}
332328
}
333329

@@ -341,11 +337,11 @@ function copyNewFile (plugin_dir, src, project_dir, dest, link) {
341337

342338
function linkFileOrDirTree (src, dest) {
343339
if (fs.existsSync(dest)) {
344-
shell.rm('-Rf', dest);
340+
fs.removeSync(dest);
345341
}
346342

347343
if (fs.statSync(src).isDirectory()) {
348-
shell.mkdir('-p', dest);
344+
fs.ensureDirSync(dest);
349345
fs.readdirSync(src).forEach(entry => {
350346
linkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
351347
});
@@ -357,12 +353,12 @@ function linkFileOrDirTree (src, dest) {
357353
// checks if file exists and then deletes. Error if doesn't exist
358354
function removeFile (project_dir, src) {
359355
const file = path.resolve(project_dir, src);
360-
shell.rm('-Rf', file);
356+
fs.removeSync(file);
361357
}
362358

363359
// deletes file/directory without checking
364360
function removeFileF (file) {
365-
shell.rm('-Rf', file);
361+
fs.removeSync(file);
366362
}
367363

368364
function removeFileAndParents (baseDir, destFile, stopper) {

bin/templates/scripts/cordova/lib/prepare.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
const Q = require('q');
2222
const fs = require('fs-extra');
2323
const path = require('path');
24-
const shell = require('shelljs');
2524
const unorm = require('unorm');
2625
const plist = require('plist');
2726
const URL = require('url');
@@ -103,7 +102,7 @@ function updateConfigFile (sourceConfig, configMunger, locations) {
103102

104103
// First cleanup current config and merge project's one into own
105104
// Overwrite platform config.xml with defaults.xml.
106-
shell.cp('-f', locations.defaultConfigXml, locations.configXml);
105+
fs.copySync(locations.defaultConfigXml, locations.configXml);
107106

108107
// Then apply config changes from global munge to all config files
109108
// in project (including project's config)

bin/templates/scripts/cordova/lib/projectFile.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const plist = require('plist');
2222
const _ = require('underscore');
2323
const path = require('path');
2424
const fs = require('fs-extra');
25-
const shell = require('shelljs');
2625

2726
const pluginHandlers = require('./plugman/pluginHandlers');
2827
const CordovaError = require('cordova-common').CordovaError;
@@ -72,7 +71,7 @@ function parseProjectFile (locations) {
7271
fs.writeFileSync(pbxPath, xcodeproj.writeSync());
7372
if (Object.keys(this.frameworks).length === 0) {
7473
// If there is no framework references remain in the project, just remove this file
75-
shell.rm('-rf', frameworks_file);
74+
fs.removeSync(frameworks_file);
7675
return;
7776
}
7877
fs.writeFileSync(frameworks_file, JSON.stringify(this.frameworks, null, 4));

bin/templates/scripts/cordova/lib/run.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
const Q = require('q');
2121
const path = require('path');
2222
const build = require('./build');
23-
const shell = require('shelljs');
2423
const superspawn = require('cordova-common').superspawn;
2524
const check_reqs = require('./check_reqs');
2625
const fs = require('fs-extra');
@@ -86,9 +85,9 @@ module.exports.run = runOptions => {
8685
// delete the existing platform/ios/build/device/appname.app
8786
fs.removeSync(appFile);
8887
// move the platform/ios/build/device/Payload/appname.app to parent
89-
shell.mv('-f', appFileInflated, buildOutputDir);
88+
fs.moveSync(appFileInflated, buildOutputDir);
9089
// delete the platform/ios/build/device/Payload folder
91-
shell.rm('-rf', payloadFolder);
90+
fs.removeSync(payloadFolder);
9291

9392
return null;
9493
})

0 commit comments

Comments
 (0)