mirror of
https://github.com/apache/cordova-android.git
synced 2026-04-23 00:00:09 +08:00
Bundle updated node modules
This commit is contained in:
committed by
Nikhil Khandelwal
parent
72bbe9fdf0
commit
d6fe1a65eb
+25
-21
@@ -17,13 +17,17 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var bplist = require('bplist-parser');
|
||||
var et = require('elementtree');
|
||||
var glob = require('glob');
|
||||
var plist = require('plist');
|
||||
var modules = {};
|
||||
var addProperty = require('../util/addProperty');
|
||||
|
||||
var plist_helpers = require('../util/plist-helpers');
|
||||
var xml_helpers = require('../util/xml-helpers');
|
||||
// Use delay loading to ensure plist and other node modules to not get loaded
|
||||
// on Android, Windows platforms
|
||||
addProperty(module, 'bplist', 'bplist-parser', modules);
|
||||
addProperty(module, 'et', 'elementtree', modules);
|
||||
addProperty(module, 'glob', 'glob', modules);
|
||||
addProperty(module, 'plist', 'plist', modules);
|
||||
addProperty(module, 'plist_helpers', '../util/plist-helpers', modules);
|
||||
addProperty(module, 'xml_helpers', '../util/xml-helpers', modules);
|
||||
|
||||
/******************************************************************************
|
||||
* ConfigFile class
|
||||
@@ -67,7 +71,7 @@ function ConfigFile_load() {
|
||||
// the same in a future release
|
||||
if (ext == '.xml' || ext == '.appxmanifest') {
|
||||
self.type = 'xml';
|
||||
self.data = xml_helpers.parseElementtreeSync(filepath);
|
||||
self.data = modules.xml_helpers.parseElementtreeSync(filepath);
|
||||
} else {
|
||||
// plist file
|
||||
self.type = 'plist';
|
||||
@@ -76,8 +80,8 @@ function ConfigFile_load() {
|
||||
// Do we still need to support binary plist?
|
||||
// If yes, use plist.parseStringSync() and read the file once.
|
||||
self.data = isBinaryPlist(filepath) ?
|
||||
bplist.parseBuffer(fs.readFileSync(filepath)) :
|
||||
plist.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
modules.bplist.parseBuffer(fs.readFileSync(filepath)) :
|
||||
modules.plist.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ ConfigFile.prototype.save = function ConfigFile_save() {
|
||||
} else {
|
||||
// plist
|
||||
var regExp = new RegExp('<string>[ \t\r\n]+?</string>', 'g');
|
||||
fs.writeFileSync(self.filepath, plist.build(self.data).replace(regExp, '<string></string>'));
|
||||
fs.writeFileSync(self.filepath, modules.plist.build(self.data).replace(regExp, '<string></string>'));
|
||||
}
|
||||
self.is_changed = false;
|
||||
};
|
||||
@@ -98,16 +102,16 @@ ConfigFile.prototype.graft_child = function ConfigFile_graft_child(selector, xml
|
||||
var filepath = self.filepath;
|
||||
var result;
|
||||
if (self.type === 'xml') {
|
||||
var xml_to_graft = [et.XML(xml_child.xml)];
|
||||
result = xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
|
||||
var xml_to_graft = [modules.et.XML(xml_child.xml)];
|
||||
result = modules.xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
|
||||
if ( !result) {
|
||||
throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
|
||||
throw new Error('Unable to graft xml at selector "' + selector + '" from "' + filepath + '" during config install');
|
||||
}
|
||||
} else {
|
||||
// plist file
|
||||
result = plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
|
||||
result = modules.plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
|
||||
if ( !result ) {
|
||||
throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
|
||||
throw new Error('Unable to graft plist "' + filepath + '" during config install');
|
||||
}
|
||||
}
|
||||
self.is_changed = true;
|
||||
@@ -118,11 +122,11 @@ ConfigFile.prototype.prune_child = function ConfigFile_prune_child(selector, xml
|
||||
var filepath = self.filepath;
|
||||
var result;
|
||||
if (self.type === 'xml') {
|
||||
var xml_to_graft = [et.XML(xml_child.xml)];
|
||||
result = xml_helpers.pruneXML(self.data, xml_to_graft, selector);
|
||||
var xml_to_graft = [modules.et.XML(xml_child.xml)];
|
||||
result = modules.xml_helpers.pruneXML(self.data, xml_to_graft, selector);
|
||||
} else {
|
||||
// plist file
|
||||
result = plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
|
||||
result = modules.plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
|
||||
}
|
||||
if (!result) {
|
||||
var err_msg = 'Pruning at selector "' + selector + '" from "' + filepath + '" went bad.';
|
||||
@@ -140,7 +144,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
|
||||
|
||||
if (file.indexOf('*') > -1) {
|
||||
// handle wildcards in targets using glob.
|
||||
matches = glob.sync(path.join(project_dir, '**', file));
|
||||
matches = modules.glob.sync(path.join(project_dir, '**', file));
|
||||
if (matches.length) filepath = matches[0];
|
||||
|
||||
// [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
|
||||
@@ -167,7 +171,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
|
||||
} else if (platform == 'android') {
|
||||
filepath = path.join(project_dir, 'res', 'xml', 'config.xml');
|
||||
} else {
|
||||
matches = glob.sync(path.join(project_dir, '**', 'config.xml'));
|
||||
matches = modules.glob.sync(path.join(project_dir, '**', 'config.xml'));
|
||||
if (matches.length) filepath = matches[0];
|
||||
}
|
||||
return filepath;
|
||||
@@ -180,7 +184,7 @@ function resolveConfigFilePath(project_dir, platform, file) {
|
||||
// Find out the real name of an iOS project
|
||||
// TODO: glob is slow, need a better way or caching, or avoid using more than once.
|
||||
function getIOSProjectname(project_dir) {
|
||||
var matches = glob.sync(path.join(project_dir, '*.xcodeproj'));
|
||||
var matches = modules.glob.sync(path.join(project_dir, '*.xcodeproj'));
|
||||
var iospath;
|
||||
if (matches.length === 1) {
|
||||
iospath = path.basename(matches[0],'.xcodeproj');
|
||||
|
||||
+5
-5
@@ -89,7 +89,7 @@ CordovaLogger.prototype.log = function (logLevel, message) {
|
||||
var isVerbose = this.logLevel === 'verbose';
|
||||
var cursor = this.stdoutCursor;
|
||||
|
||||
if(message instanceof Error || logLevel === CordovaLogger.ERROR) {
|
||||
if (message instanceof Error || logLevel === CordovaLogger.ERROR) {
|
||||
message = formatError(message, isVerbose);
|
||||
cursor = this.stderrCursor;
|
||||
}
|
||||
@@ -196,10 +196,10 @@ CordovaLogger.prototype.subscribe = function (eventEmitter) {
|
||||
function formatError(error, isVerbose) {
|
||||
var message = '';
|
||||
|
||||
if(error instanceof CordovaError) {
|
||||
if (error instanceof CordovaError) {
|
||||
message = error.toString(isVerbose);
|
||||
} else if(error instanceof Error) {
|
||||
if(isVerbose) {
|
||||
} else if (error instanceof Error) {
|
||||
if (isVerbose) {
|
||||
message = error.stack;
|
||||
} else {
|
||||
message = error.message;
|
||||
@@ -209,7 +209,7 @@ function formatError(error, isVerbose) {
|
||||
message = error;
|
||||
}
|
||||
|
||||
if(message.toUpperCase().indexOf('ERROR:') !== 0) {
|
||||
if (typeof message === 'string' && message.toUpperCase().indexOf('ERROR:') !== 0) {
|
||||
// Needed for backward compatibility with external tools
|
||||
message = 'Error: ' + message;
|
||||
}
|
||||
|
||||
+422
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var shell = require("shelljs");
|
||||
var minimatch = require("minimatch");
|
||||
|
||||
/**
|
||||
* Logging callback used in the FileUpdater methods.
|
||||
* @callback loggingCallback
|
||||
* @param {string} message A message describing a single file update operation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Updates a target file or directory with a source file or directory. (Directory updates are
|
||||
* not recursive.) Stats for target and source items must be passed in. This is an internal
|
||||
* helper function used by other methods in this module.
|
||||
*
|
||||
* @param {?string} sourcePath Source file or directory to be used to update the
|
||||
* destination. If the source is null, then the destination is deleted if it exists.
|
||||
* @param {?fs.Stats} sourceStats An instance of fs.Stats for the source path, or null if
|
||||
* the source does not exist.
|
||||
* @param {string} targetPath Required destination file or directory to be updated. If it does
|
||||
* not exist, it will be created.
|
||||
* @param {?fs.Stats} targetStats An instance of fs.Stats for the target path, or null if
|
||||
* the target does not exist.
|
||||
* @param {Object} [options] Optional additional parameters for the update.
|
||||
* @param {string} [options.rootDir] Optional root directory (such as a project) to which target
|
||||
* and source path parameters are relative; may be omitted if the paths are absolute. The
|
||||
* rootDir is always omitted from any logged paths, to make the logs easier to read.
|
||||
* @param {boolean} [options.all] If true, all files are copied regardless of last-modified times.
|
||||
* Otherwise, a file is copied if the source's last-modified time is greather than or
|
||||
* equal to the target's last-modified time, or if the file sizes are different.
|
||||
* @param {loggingCallback} [log] Optional logging callback that takes a string message
|
||||
* describing any file operations that are performed.
|
||||
* @return {boolean} true if any changes were made, or false if the force flag is not set
|
||||
* and everything was up to date
|
||||
*/
|
||||
function updatePathWithStats(sourcePath, sourceStats, targetPath, targetStats, options, log) {
|
||||
var updated = false;
|
||||
|
||||
var rootDir = (options && options.rootDir) || "";
|
||||
var copyAll = (options && options.all) || false;
|
||||
|
||||
var targetFullPath = path.join(rootDir || "", targetPath);
|
||||
|
||||
if (sourceStats) {
|
||||
var sourceFullPath = path.join(rootDir || "", sourcePath);
|
||||
|
||||
if (targetStats) {
|
||||
// The target exists. But if the directory status doesn't match the source, delete it.
|
||||
if (targetStats.isDirectory() && !sourceStats.isDirectory()) {
|
||||
log("rmdir " + targetPath + " (source is a file)");
|
||||
shell.rm("-rf", targetFullPath);
|
||||
targetStats = null;
|
||||
updated = true;
|
||||
} else if (!targetStats.isDirectory() && sourceStats.isDirectory()) {
|
||||
log("delete " + targetPath + " (source is a directory)");
|
||||
shell.rm("-f", targetFullPath);
|
||||
targetStats = null;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetStats) {
|
||||
if (sourceStats.isDirectory()) {
|
||||
// The target directory does not exist, so it should be created.
|
||||
log("mkdir " + targetPath);
|
||||
shell.mkdir("-p", targetFullPath);
|
||||
updated = true;
|
||||
} else if (sourceStats.isFile()) {
|
||||
// The target file does not exist, so it should be copied from the source.
|
||||
log("copy " + sourcePath + " " + targetPath + (copyAll ? "" : " (new file)"));
|
||||
shell.cp("-f", sourceFullPath, targetFullPath);
|
||||
updated = true;
|
||||
}
|
||||
} else if (sourceStats.isFile() && targetStats.isFile()) {
|
||||
// The source and target paths both exist and are files.
|
||||
if (copyAll) {
|
||||
// The caller specified all files should be copied.
|
||||
log("copy " + sourcePath + " " + targetPath);
|
||||
shell.cp("-f", sourceFullPath, targetFullPath);
|
||||
updated = true;
|
||||
} else {
|
||||
// Copy if the source has been modified since it was copied to the target, or if
|
||||
// the file sizes are different. (The latter catches most cases in which something
|
||||
// was done to the file after copying.) Comparison is >= rather than > to allow
|
||||
// for timestamps lacking sub-second precision in some filesystems.
|
||||
if (sourceStats.mtime.getTime() >= targetStats.mtime.getTime() ||
|
||||
sourceStats.size !== targetStats.size) {
|
||||
log("copy " + sourcePath + " " + targetPath + " (updated file)");
|
||||
shell.cp("-f", sourceFullPath, targetFullPath);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (targetStats) {
|
||||
// The target exists but the source is null, so the target should be deleted.
|
||||
if (targetStats.isDirectory()) {
|
||||
log("rmdir " + targetPath + (copyAll ? "" : " (no source)"));
|
||||
shell.rm("-rf", targetFullPath);
|
||||
} else {
|
||||
log("delete " + targetPath + (copyAll ? "" : " (no source)"));
|
||||
shell.rm("-f", targetFullPath);
|
||||
}
|
||||
updated = true;
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for updatePath and updatePaths functions. Queries stats for source and target
|
||||
* and ensures target directory exists before copying a file.
|
||||
*/
|
||||
function updatePathInternal(sourcePath, targetPath, options, log) {
|
||||
var rootDir = (options && options.rootDir) || "";
|
||||
var targetFullPath = path.join(rootDir, targetPath);
|
||||
var targetStats = fs.existsSync(targetFullPath) ? fs.statSync(targetFullPath) : null;
|
||||
var sourceStats = null;
|
||||
|
||||
if (sourcePath) {
|
||||
// A non-null source path was specified. It should exist.
|
||||
var sourceFullPath = path.join(rootDir, sourcePath);
|
||||
if (!fs.existsSync(sourceFullPath)) {
|
||||
throw new Error("Source path does not exist: " + sourcePath);
|
||||
}
|
||||
|
||||
sourceStats = fs.statSync(sourceFullPath);
|
||||
|
||||
// Create the target's parent directory if it doesn't exist.
|
||||
var parentDir = path.dirname(targetFullPath);
|
||||
if (!fs.existsSync(parentDir)) {
|
||||
shell.mkdir("-p", parentDir);
|
||||
}
|
||||
}
|
||||
|
||||
return updatePathWithStats(sourcePath, sourceStats, targetPath, targetStats, options, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a target file or directory with a source file or directory. (Directory updates are
|
||||
* not recursive.)
|
||||
*
|
||||
* @param {?string} sourcePath Source file or directory to be used to update the
|
||||
* destination. If the source is null, then the destination is deleted if it exists.
|
||||
* @param {string} targetPath Required destination file or directory to be updated. If it does
|
||||
* not exist, it will be created.
|
||||
* @param {Object} [options] Optional additional parameters for the update.
|
||||
* @param {string} [options.rootDir] Optional root directory (such as a project) to which target
|
||||
* and source path parameters are relative; may be omitted if the paths are absolute. The
|
||||
* rootDir is always omitted from any logged paths, to make the logs easier to read.
|
||||
* @param {boolean} [options.all] If true, all files are copied regardless of last-modified times.
|
||||
* Otherwise, a file is copied if the source's last-modified time is greather than or
|
||||
* equal to the target's last-modified time, or if the file sizes are different.
|
||||
* @param {loggingCallback} [log] Optional logging callback that takes a string message
|
||||
* describing any file operations that are performed.
|
||||
* @return {boolean} true if any changes were made, or false if the force flag is not set
|
||||
* and everything was up to date
|
||||
*/
|
||||
function updatePath(sourcePath, targetPath, options, log) {
|
||||
if (sourcePath !== null && typeof sourcePath !== "string") {
|
||||
throw new Error("A source path (or null) is required.");
|
||||
}
|
||||
|
||||
if (!targetPath || typeof targetPath !== "string") {
|
||||
throw new Error("A target path is required.");
|
||||
}
|
||||
|
||||
log = log || function(message) { };
|
||||
|
||||
return updatePathInternal(sourcePath, targetPath, options, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates files and directories based on a mapping from target paths to source paths. Targets
|
||||
* with null sources in the map are deleted.
|
||||
*
|
||||
* @param {Object} pathMap A dictionary mapping from target paths to source paths.
|
||||
* @param {Object} [options] Optional additional parameters for the update.
|
||||
* @param {string} [options.rootDir] Optional root directory (such as a project) to which target
|
||||
* and source path parameters are relative; may be omitted if the paths are absolute. The
|
||||
* rootDir is always omitted from any logged paths, to make the logs easier to read.
|
||||
* @param {boolean} [options.all] If true, all files are copied regardless of last-modified times.
|
||||
* Otherwise, a file is copied if the source's last-modified time is greather than or
|
||||
* equal to the target's last-modified time, or if the file sizes are different.
|
||||
* @param {loggingCallback} [log] Optional logging callback that takes a string message
|
||||
* describing any file operations that are performed.
|
||||
* @return {boolean} true if any changes were made, or false if the force flag is not set
|
||||
* and everything was up to date
|
||||
*/
|
||||
function updatePaths(pathMap, options, log) {
|
||||
if (!pathMap || typeof pathMap !== "object" || Array.isArray(pathMap)) {
|
||||
throw new Error("An object mapping from target paths to source paths is required.");
|
||||
}
|
||||
|
||||
log = log || function(message) { };
|
||||
|
||||
var updated = false;
|
||||
|
||||
// Iterate in sorted order to ensure directories are created before files under them.
|
||||
Object.keys(pathMap).sort().forEach(function (targetPath) {
|
||||
var sourcePath = pathMap[targetPath];
|
||||
updated = updatePathInternal(sourcePath, targetPath, options, log) || updated;
|
||||
});
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a target directory with merged files and subdirectories from source directories.
|
||||
*
|
||||
* @param {string|string[]} sourceDirs Required source directory or array of source directories
|
||||
* to be merged into the target. The directories are listed in order of precedence; files in
|
||||
* directories later in the array supersede files in directories earlier in the array
|
||||
* (regardless of timestamps).
|
||||
* @param {string} targetDir Required destination directory to be updated. If it does not exist,
|
||||
* it will be created. If it exists, newer files from source directories will be copied over,
|
||||
* and files missing in the source directories will be deleted.
|
||||
* @param {Object} [options] Optional additional parameters for the update.
|
||||
* @param {string} [options.rootDir] Optional root directory (such as a project) to which target
|
||||
* and source path parameters are relative; may be omitted if the paths are absolute. The
|
||||
* rootDir is always omitted from any logged paths, to make the logs easier to read.
|
||||
* @param {boolean} [options.all] If true, all files are copied regardless of last-modified times.
|
||||
* Otherwise, a file is copied if the source's last-modified time is greather than or
|
||||
* equal to the target's last-modified time, or if the file sizes are different.
|
||||
* @param {string|string[]} [options.include] Optional glob string or array of glob strings that
|
||||
* are tested against both target and source relative paths to determine if they are included
|
||||
* in the merge-and-update. If unspecified, all items are included.
|
||||
* @param {string|string[]} [options.exclude] Optional glob string or array of glob strings that
|
||||
* are tested against both target and source relative paths to determine if they are excluded
|
||||
* from the merge-and-update. Exclusions override inclusions. If unspecified, no items are
|
||||
* excluded.
|
||||
* @param {loggingCallback} [log] Optional logging callback that takes a string message
|
||||
* describing any file operations that are performed.
|
||||
* @return {boolean} true if any changes were made, or false if the force flag is not set
|
||||
* and everything was up to date
|
||||
*/
|
||||
function mergeAndUpdateDir(sourceDirs, targetDir, options, log) {
|
||||
if (sourceDirs && typeof sourceDirs === "string") {
|
||||
sourceDirs = [ sourceDirs ];
|
||||
} else if (!Array.isArray(sourceDirs)) {
|
||||
throw new Error("A source directory path or array of paths is required.");
|
||||
}
|
||||
|
||||
if (!targetDir || typeof targetDir !== "string") {
|
||||
throw new Error("A target directory path is required.");
|
||||
}
|
||||
|
||||
log = log || function(message) { };
|
||||
|
||||
var rootDir = (options && options.rootDir) || "";
|
||||
|
||||
var include = (options && options.include) || [ "**" ];
|
||||
if (typeof include === "string") {
|
||||
include = [ include ];
|
||||
} else if (!Array.isArray(include)) {
|
||||
throw new Error("Include parameter must be a glob string or array of glob strings.");
|
||||
}
|
||||
|
||||
var exclude = (options && options.exclude) || [];
|
||||
if (typeof exclude === "string") {
|
||||
exclude = [ exclude ];
|
||||
} else if (!Array.isArray(exclude)) {
|
||||
throw new Error("Exclude parameter must be a glob string or array of glob strings.");
|
||||
}
|
||||
|
||||
// Scan the files in each of the source directories.
|
||||
var sourceMaps = [];
|
||||
for (var i in sourceDirs) {
|
||||
var sourceFullPath = path.join(rootDir, sourceDirs[i]);
|
||||
if (!fs.existsSync(sourceFullPath)) {
|
||||
throw new Error("Source directory does not exist: " + sourceDirs[i]);
|
||||
}
|
||||
sourceMaps[i] = mapDirectory(rootDir, sourceDirs[i], include, exclude);
|
||||
}
|
||||
|
||||
// Scan the files in the target directory, if it exists.
|
||||
var targetMap = {};
|
||||
var targetFullPath = path.join(rootDir, targetDir);
|
||||
if (fs.existsSync(targetFullPath)) {
|
||||
targetMap = mapDirectory(rootDir, targetDir, include, exclude);
|
||||
}
|
||||
|
||||
var pathMap = mergePathMaps(sourceMaps, targetMap, targetDir);
|
||||
|
||||
var updated = false;
|
||||
|
||||
// Iterate in sorted order to ensure directories are created before files under them.
|
||||
Object.keys(pathMap).sort().forEach(function (subPath) {
|
||||
var entry = pathMap[subPath];
|
||||
updated = updatePathWithStats(
|
||||
entry.sourcePath,
|
||||
entry.sourceStats,
|
||||
entry.targetPath,
|
||||
entry.targetStats,
|
||||
options,
|
||||
log) || updated;
|
||||
});
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dictionary map of all files and directories under a path.
|
||||
*/
|
||||
function mapDirectory(rootDir, subDir, include, exclude) {
|
||||
var dirMap = { "": { subDir: subDir, stats: fs.statSync(path.join(rootDir, subDir)) } };
|
||||
mapSubdirectory(rootDir, subDir, "", include, exclude, dirMap);
|
||||
return dirMap;
|
||||
|
||||
function mapSubdirectory(rootDir, subDir, relativeDir, include, exclude, dirMap) {
|
||||
var itemMapped = false;
|
||||
var items = fs.readdirSync(path.join(rootDir, subDir, relativeDir));
|
||||
for (var i in items) {
|
||||
var relativePath = path.join(relativeDir, items[i]);
|
||||
|
||||
// Skip any files or directories (and everything under) that match an exclude glob.
|
||||
if (matchGlobArray(relativePath, exclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stats obtained here (required at least to know where to recurse in directories)
|
||||
// are saved for later, where the modified times may also be used. This minimizes
|
||||
// the number of file I/O operations performed.
|
||||
var fullPath = path.join(rootDir, subDir, relativePath);
|
||||
var stats = fs.statSync(fullPath);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
// Directories are included if either something under them is included or they
|
||||
// match an include glob.
|
||||
if (mapSubdirectory(rootDir, subDir, relativePath, include, exclude, dirMap) ||
|
||||
matchGlobArray(relativePath, include)) {
|
||||
dirMap[relativePath] = { subDir: subDir, stats: stats };
|
||||
itemMapped = true;
|
||||
}
|
||||
} else if (stats.isFile()) {
|
||||
// Files are included only if they match an include glob.
|
||||
if (matchGlobArray(relativePath, include)) {
|
||||
dirMap[relativePath] = { subDir: subDir, stats: stats };
|
||||
itemMapped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return itemMapped;
|
||||
}
|
||||
|
||||
function matchGlobArray(path, globs) {
|
||||
for (var i in globs) {
|
||||
if (minimatch(path, globs[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges together multiple source maps and a target map into a single mapping from
|
||||
* relative paths to objects with target and source paths and stats.
|
||||
*/
|
||||
function mergePathMaps(sourceMaps, targetMap, targetDir) {
|
||||
// Merge multiple source maps together, along with target path info.
|
||||
// Entries in later source maps override those in earlier source maps.
|
||||
// Target stats will be filled in below for targets that exist.
|
||||
var pathMap = {};
|
||||
sourceMaps.forEach(function (sourceMap) {
|
||||
for (var sourceSubPath in sourceMap) {
|
||||
var sourceEntry = sourceMap[sourceSubPath];
|
||||
pathMap[sourceSubPath] = {
|
||||
targetPath: path.join(targetDir, sourceSubPath),
|
||||
targetStats: null,
|
||||
sourcePath: path.join(sourceEntry.subDir, sourceSubPath),
|
||||
sourceStats: sourceEntry.stats
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Fill in target stats for targets that exist, and create entries
|
||||
// for targets that don't have any corresponding sources.
|
||||
for (var subPath in targetMap) {
|
||||
var entry = pathMap[subPath];
|
||||
if (entry) {
|
||||
entry.targetStats = targetMap[subPath].stats;
|
||||
} else {
|
||||
pathMap[subPath] = {
|
||||
targetPath: path.join(targetDir, subPath),
|
||||
targetStats: targetMap[subPath].stats,
|
||||
sourcePath: null,
|
||||
sourceStats: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
updatePath: updatePath,
|
||||
updatePaths: updatePaths,
|
||||
mergeAndUpdateDir: mergeAndUpdateDir
|
||||
};
|
||||
|
||||
+1
-1
@@ -331,7 +331,7 @@ function PluginInfo(dirname) {
|
||||
///// PluginInfo Constructor logic /////
|
||||
self.filepath = path.join(dirname, 'plugin.xml');
|
||||
if (!fs.existsSync(self.filepath)) {
|
||||
throw new CordovaError('Cannot find plugin.xml for plugin \'' + path.basename(dirname) + '\'. Please try adding it again.');
|
||||
throw new CordovaError('Cannot find plugin.xml for plugin "' + path.basename(dirname) + '". Please try adding it again.');
|
||||
}
|
||||
|
||||
self.dir = dirname;
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ module.exports.forwardEventsTo = function (eventEmitter) {
|
||||
}
|
||||
|
||||
if (!(eventEmitter instanceof EventEmitter))
|
||||
throw new Error('Cordova events could be redirected to another EventEmitter instance only');
|
||||
throw new Error('Cordova events can be redirected to another EventEmitter instance only');
|
||||
|
||||
// CB-10940 Skipping forwarding to self to avoid infinite recursion.
|
||||
// This is the case when the modules are npm-linked.
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
module.exports = function addProperty(module, property, modulePath, obj) {
|
||||
|
||||
obj = obj || module.exports;
|
||||
// Add properties as getter to delay load the modules on first invocation
|
||||
Object.defineProperty(obj, property, {
|
||||
configurable: true,
|
||||
get: function () {
|
||||
var delayLoadedModule = module.require(modulePath);
|
||||
obj[property] = delayLoadedModule;
|
||||
return delayLoadedModule;
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user