diff --git a/spec/cordova/metadata/browser_parser.spec.js b/spec/cordova/metadata/browser_parser.spec.js deleted file mode 100644 index 8f94c0ed2..000000000 --- a/spec/cordova/metadata/browser_parser.spec.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - 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. -*/ - -var browserParser = require('../../../src/cordova/metadata/browser_parser'); -var util = require('../../../src/cordova/util'); -var path = require('path'); -var shell = require('shelljs'); -var fs = require('fs'); -var Parser = require('../../../src/cordova/metadata/parser'); - -describe('browser project parser', function () { - var proj = path.join('some', 'path'); - var exists; - - beforeEach(function () { - exists = spyOn(fs, 'existsSync').and.returnValue(true); - spyOn(browserParser, 'dirExists').and.returnValue(true); - }); - - describe('constructions', function () { - it('should create an instance with a path', function () { - expect(function () { - var p = new browserParser(proj); // eslint-disable-line new-cap - expect(p.path).toEqual(proj); - }).not.toThrow(); - }); - it('should be an instance of Parser', function () { - expect(new browserParser(proj) instanceof Parser).toBe(true); // eslint-disable-line new-cap - }); - it('should call super with the correct arguments', function () { - var call = spyOn(Parser, 'call'); - var p = new browserParser(proj); // eslint-disable-line new-cap - expect(call).toHaveBeenCalledWith(p, 'browser', proj); - }); - }); - - describe('instance', function () { - var p; - var cp; - var rm; - var mkdir; // eslint-disable-line no-unused-vars - var is_cordova; // eslint-disable-line no-unused-vars - var browser_proj = path.join(proj, 'platforms', 'browser'); - - beforeEach(function () { - p = new browserParser(browser_proj); // eslint-disable-line new-cap - cp = spyOn(shell, 'cp'); - rm = spyOn(shell, 'rm'); - mkdir = spyOn(shell, 'mkdir'); - is_cordova = spyOn(util, 'isCordova').and.returnValue(proj); - }); - - describe('www_dir method', function () { - it('should return /www', function () { - expect(p.www_dir()).toEqual(path.join(browser_proj, 'www')); - }); - }); - - describe('config_xml method', function () { - it('should return the location of config.xml', function () { - expect(p.config_xml()).toEqual(path.join(proj, 'platforms', 'browser', 'config.xml')); - }); - }); - - describe('update_www method', function () { - it('should rm project-level www and cp in platform agnostic www', function () { - p.update_www(); - expect(rm).toHaveBeenCalled(); - expect(cp).toHaveBeenCalled(); - }); - }); - - describe('update_overrides method', function () { - it('should do nothing if merges directory does not exist', function () { - exists.and.returnValue(false); - p.update_overrides(); - expect(cp).not.toHaveBeenCalled(); - }); - - it('should copy merges path into www', function () { - p.update_overrides(); - expect(cp).toHaveBeenCalledWith('-rf', path.join(proj, 'merges', 'browser', '*'), path.join(proj, 'platforms', 'browser', 'www')); - }); - }); - }); -}); diff --git a/spec/plugman/platforms/amazon-fireos.spec.js b/spec/plugman/platforms/amazon-fireos.spec.js deleted file mode 100644 index c693689c6..000000000 --- a/spec/plugman/platforms/amazon-fireos.spec.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - 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. -*/ -/* -var amazon_fireos = require('../../../src/plugman/platforms/amazon-fireos'), - common = require('../../../src/plugman/platforms/common'), - install = require('../../../src/plugman/install'), - path = require('path'), - fs = require('fs'), - shell = require('shelljs'), - et = require('elementtree'), - os = require('osenv'), - temp = path.join(os.tmpdir(), 'plugman'), - plugins_dir = path.join(temp, 'cordova', 'plugins'), - xml_helpers = require('../../../src/util/xml-helpers'), - plugins_module = require('../../../src/plugman/util/plugins'), - dummyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.dummyplugin'), - faultyplugin = path.join(__dirname, '..', 'plugins', 'org.test.plugins.faultyplugin'), - amazon_fireos_one_project = path.join(__dirname, '..', 'projects', 'android_one', '*'), - amazon_fireos_two_project = path.join(__dirname, '..', 'projects', 'android_two', '*'); - -var PluginInfo = require('../../../src/PluginInfo'); - -var dummyPluginInfo = new PluginInfo(dummyplugin); -var dummy_id = dummyPluginInfo.id; -var valid_source = dummyPluginInfo.getSourceFiles('amazon-fireos'); - -var faultyPluginInfo = new PluginInfo(faultyplugin); -var invalid_source = faultyPluginInfo.getSourceFiles('amazon-fireos'); - -function copyArray(arr) { - return Array.prototype.slice.call(arr, 0); -} -*/ -/* -describe('amazon-fireos project handler', function() { - describe('www_dir method', function() { - it('should return cordova-amazon-fireos project www location using www_dir', function() { - expect(amazon_fireos.www_dir(path.sep)).toEqual(path.sep + path.join('assets', 'www')); - }); - }); - describe('package_name method', function() { - it('should return an amazon-fireos project\'s proper package name', function() { - expect(amazon_fireos.package_name(path.join(amazon_fireos_one_project, '..'))).toEqual('com.alunny.childapp'); - }); - }); - - describe('installation', function() { - beforeEach(function() { - shell.mkdir('-p', temp); - }); - afterEach(function() { - shell.rm('-rf', temp); - }); - describe('of elements', function() { - it("should copy jar files to project/libs", function () { - var s = spyOn(common, 'copyFile'); - - amazon_fireos['lib-file'].install(valid_libs[0], dummyplugin, temp); - expect(s).toHaveBeenCalledWith(dummyplugin, 'src/amazon-fireos/TestLib.jar', temp, path.join('libs', 'TestLib.jar')); - }); - }); - describe('of elements', function() { - beforeEach(function() { - shell.cp('-rf', amazon_fireos_one_project, temp); - }); - - it('should copy stuff from one location to another by calling common.copyFile', function() { - var source = copyArray(valid_source); - var s = spyOn(common, 'copyFile'); - amazon_fireos['source-file'].install(source[0], dummyplugin, temp); - expect(s).toHaveBeenCalledWith(dummyplugin, 'src/amazon-fireos/DummyPlugin.java', temp, path.join('src', 'com', 'phonegap', 'plugins', 'dummyplugin', 'DummyPlugin.java')); - }); - it('should throw if source file cannot be found', function() { - var source = copyArray(invalid_source); - expect(function() { - amazon_fireos['source-file'].install(source[0], faultyplugin, temp); - }).toThrow('"' + path.resolve(faultyplugin, 'src/amazon-fireos/NotHere.java') + '" not found!'); - }); - it('should throw if target file already exists', function() { - // write out a file - var target = path.resolve(temp, 'src/com/phonegap/plugins/dummyplugin'); - shell.mkdir('-p', target); - target = path.join(target, 'DummyPlugin.java'); - fs.writeFileSync(target, 'some bs', 'utf-8'); - - var source = copyArray(valid_source); - expect(function() { - amazon_fireos['source-file'].install(source[0], dummyplugin, temp); - }).toThrow('"' + target + '" already exists!'); - }); - }); - }); - - describe('uninstallation', function() { - beforeEach(function() { - shell.mkdir('-p', temp); - shell.mkdir('-p', plugins_dir); - shell.cp('-rf', amazon_fireos_two_project, temp); - }); - afterEach(function() { - shell.rm('-rf', temp); - }); - describe('of elements', function(done) { - it('should remove jar files', function () { - var s = spyOn(common, 'removeFile'); - amazon_fireos['lib-file'].install(valid_libs[0], dummyplugin, temp); - amazon_fireos['lib-file'].uninstall(valid_libs[0], temp, dummy_id); - expect(s).toHaveBeenCalledWith(temp, path.join('libs', 'TestLib.jar')); - }); - }); - describe('of elements', function() { - it('should remove stuff by calling common.deleteJava', function(done) { - var s = spyOn(common, 'deleteJava'); - install('amazon-fireos', temp, dummyplugin, plugins_dir, {}) - .then(function() { - var source = copyArray(valid_source); - amazon_fireos['source-file'].uninstall(source[0], temp); - expect(s).toHaveBeenCalledWith(temp, path.join('src', 'com', 'phonegap', 'plugins', 'dummyplugin', 'DummyPlugin.java')); - done(); - }); - }); - }); - }); -}); */ diff --git a/spec/plugman/platforms/tizen.spec.js b/spec/plugman/platforms/tizen.spec.js deleted file mode 100644 index 163194304..000000000 --- a/spec/plugman/platforms/tizen.spec.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * - * Licensed 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. - * -*/ - -var tizen = require('../../../src/plugman/platforms/tizen'); -var os = require('os'); -var path = require('path'); -var tizen_project = path.join(__dirname, '..', 'projects', 'tizen'); - -path.join(os.tmpdir(), 'plugman-' + ((function () { - var index, subIndex; - var set = 'abcdefghijklmnopqrstuvwxyz0123456789'; - var str = ''; - - for (index = 0; index < 12; index++) { - subIndex = Math.round(Math.random() * (set.length - 1)); - str += set.substring(subIndex, subIndex + 1); - } - - return str; -})())); - -describe('Tizen project handler', function () { - describe('www_dir method', function () { - it('Test 001 : should append www to the directory passed in', function () { - expect(tizen.www_dir(path.sep)).toEqual(path.join(path.sep, 'www')); - }); - }); - describe('Manipulating project files', function () { - describe('package_name method', function () { - it('Test 002 : should return the id of the config.xml root element', function () { - expect(tizen.package_name(tizen_project)).toEqual('TizenTestPackage'); - }); - }); - }); -}); diff --git a/spec/plugman/util/csproj.spec.js b/spec/plugman/util/csproj.spec.js deleted file mode 100644 index 973bb98be..000000000 --- a/spec/plugman/util/csproj.spec.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - 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. -*/ -var csproj = require('../../../src/util/windows/csproj'); -var path = require('path'); - -var wp8_project = path.join(__dirname, '..', 'projects', 'wp8'); -var example_csproj = path.join(wp8_project, 'CordovaAppProj.csproj'); - -describe('csproj', function () { - it('Test 001 : should throw if passed in an invalid xml file path ref', function () { - expect(function () { - new csproj('blahblah'); // eslint-disable-line - }).toThrow(); - }); - it('Test 002 : should successfully parse a valid csproj file into an xml document', function () { - var doc; - expect(function () { - doc = new csproj(example_csproj); // eslint-disable-line new-cap - }).not.toThrow(); - expect(doc.xml.getroot()).toBeDefined(); - }); - - describe('write method', function () { - - }); - - describe('source file', function () { - - var page_test = path.join('src', 'UI', 'PageTest.xaml'); - var page_test_cs = path.join('src', 'UI', 'PageTest.xaml.cs'); - var lib_test = path.join('lib', 'LibraryTest.dll'); - var file_test = path.join('src', 'FileTest.cs'); - var content_test = path.join('src', 'Content.img'); - - describe('add method', function () { - var test_csproj = new csproj(example_csproj); // eslint-disable-line new-cap - it('Test 003 : should properly add .xaml files', function () { - test_csproj.addSourceFile(page_test); - expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]')).toBeTruthy(); - expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]/Generator').text).toEqual('MSBuild:Compile'); - expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]/SubType').text).toEqual('Designer'); - }); - it('Test 004 : should properly add .xaml.cs files', function () { - test_csproj.addSourceFile(page_test_cs); - expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]')).toBeTruthy(); - expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]/DependentUpon').text).toEqual('PageTest.xaml'); - }); - it('Test 005 : should properly add .cs files', function () { - test_csproj.addSourceFile(file_test); - expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\FileTest.cs"]')).toBeTruthy(); - }); - it('Test 006 : should properly add content files', function () { - test_csproj.addSourceFile(content_test); - expect(test_csproj.xml.getroot().find('.//Content[@Include="src\\Content.img"]')).toBeTruthy(); - }); - }); - - describe('remove method', function () { - var test_csproj = new csproj(example_csproj); // eslint-disable-line new-cap - it('Test 007 : should properly remove .xaml pages', function () { - test_csproj.removeSourceFile(page_test); - expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]')).toBeFalsy(); - }); - it('Test 008 : should properly remove .xaml.cs files', function () { - test_csproj.removeSourceFile(page_test_cs); - expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]')).toBeFalsy(); - }); - it('Test 009 : should properly remove .cs files', function () { - test_csproj.removeSourceFile(file_test); - expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\FileTest.cs"]')).toBeFalsy(); - }); - it('Test 010 : should properly remove content files', function () { - test_csproj.removeSourceFile(content_test); - expect(test_csproj.xml.getroot().find('.//Content[@Include="src\\Content.img"]')).toBeFalsy(); - }); - it('Test 011 : should remove all empty ItemGroup\'s', function () { - test_csproj.removeSourceFile(page_test); - test_csproj.removeSourceFile(page_test_cs); - test_csproj.removeSourceFile(lib_test); - test_csproj.removeSourceFile(file_test); - var item_groups = test_csproj.xml.findall('ItemGroup'); - for (var i = 0, l = item_groups.length; i < l; i++) { - var group = item_groups[i]; - expect(group._children.length).toBeGreaterThan(0); - } - }); - - }); - }); -}); diff --git a/src/cordova/metadata/browser_parser.js b/src/cordova/metadata/browser_parser.js deleted file mode 100644 index 94f91e8b5..000000000 --- a/src/cordova/metadata/browser_parser.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - 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. -*/ - -var fs = require('fs'); -var path = require('path'); -var shell = require('shelljs'); -var util = require('../util'); -var CordovaError = require('cordova-common').CordovaError; -var Q = require('q'); -var Parser = require('./parser'); - -function dirExists (dir) { - return fs.existsSync(dir) && fs.statSync(dir).isDirectory(); -} - -function browser_parser (project) { - if (!module.exports.dirExists(project) || !module.exports.dirExists(path.join(project, 'cordova'))) { - throw new CordovaError('The provided path "' + project + '" is not a valid browser project.'); - } - - // Call the base class constructor - Parser.call(this, 'browser', project); - - this.path = project; -} - -require('util').inherits(browser_parser, Parser); - -module.exports = browser_parser; - -// Returns a promise. -browser_parser.prototype.update_from_config = function () { - return Q(); -}; - -browser_parser.prototype.www_dir = function () { - return path.join(this.path, 'www'); -}; - -// Used for creating platform_www in projects created by older versions. -browser_parser.prototype.cordovajs_path = function (libDir) { - var jsPath = path.join(libDir, 'cordova-lib', 'cordova.js'); - return path.resolve(jsPath); -}; - -browser_parser.prototype.cordovajs_src_path = function (libDir) { - var jsPath = path.join(libDir, 'cordova-js-src'); - return path.resolve(jsPath); -}; - -// Replace the www dir with contents of platform_www and app www. -browser_parser.prototype.update_www = function () { - var projectRoot = util.isCordova(this.path); - var app_www = util.projectWww(projectRoot); - var platform_www = path.join(this.path, 'platform_www'); - - // Clear the www dir - shell.rm('-rf', this.www_dir()); - shell.mkdir(this.www_dir()); - // Copy over all app www assets - shell.cp('-rf', path.join(app_www, '*'), this.www_dir()); - // Copy over stock platform www assets (cordova.js) - shell.cp('-rf', path.join(platform_www, '*'), this.www_dir()); -}; - -browser_parser.prototype.update_overrides = function () { - var projectRoot = util.isCordova(this.path); - var mergesPath = path.join(util.appDir(projectRoot), 'merges', 'browser'); - if (fs.existsSync(mergesPath)) { - var overrides = path.join(mergesPath, '*'); - shell.cp('-rf', overrides, this.www_dir()); - } -}; - -browser_parser.prototype.config_xml = function () { - return path.join(this.path, 'config.xml'); -}; - -// Returns a promise. -browser_parser.prototype.update_project = function (cfg) { - return this.update_from_config() - .then(function () { - this.update_overrides(); - util.deleteSvnFolders(this.www_dir()); - - // Copy munged config.xml to platform www dir - shell.cp('-rf', path.join(this.www_dir(), '..', 'config.xml'), this.www_dir()); - }.bind(this)); -}; - -module.exports.dirExists = dirExists; diff --git a/src/plugman/platforms/browser.js b/src/plugman/platforms/browser.js deleted file mode 100644 index 833786f69..000000000 --- a/src/plugman/platforms/browser.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - 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. -*/ - -var path = require('path'); -var common = require('./common'); -var events = require('cordova-common').events; - -module.exports = { - www_dir: function (project_dir) { - return path.join(project_dir, 'www'); - }, - package_name: function (project_dir) { - return common.package_name(project_dir, this.www_dir(project_dir)); - }, - 'source-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - var dest = path.join(obj.targetDir, path.basename(obj.src)); - common.copyFile(plugin_dir, obj.src, project_dir, dest); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - var dest = path.join(obj.targetDir, path.basename(obj.src)); - common.removeFile(project_dir, dest); - } - }, - 'header-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'header-fileinstall is not supported for browser'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'header-file.uninstall is not supported for browser'); - } - }, - 'resource-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'resource-file.install is not supported for browser'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'resource-file.uninstall is not supported for browser'); - } - }, - 'framework': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'framework.install is not supported for browser'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'framework.uninstall is not supported for browser'); - } - }, - 'lib-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'lib-file.install is not supported for browser'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'lib-file.uninstall is not supported for browser'); - } - } -}; diff --git a/src/plugman/platforms/tizen.js b/src/plugman/platforms/tizen.js deleted file mode 100644 index 42103f4f1..000000000 --- a/src/plugman/platforms/tizen.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - 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. -*/ - -var path = require('path'); -var fs = require('fs'); -var events = require('cordova-common').events; -var xml_helpers = require('cordova-common').xmlHelpers; - -module.exports = { - www_dir: function (project_dir) { - return path.join(project_dir, 'www'); - }, - package_name: function (project_dir) { - // preferred location if cordova >= 3.4 - var preferred_path = path.join(project_dir, 'config.xml'); - var config_path; - if (!fs.existsSync(preferred_path)) { - // older location - var old_config_path = path.join(module.exports.www_dir(project_dir), 'config.xml'); - if (!fs.existsSync(old_config_path)) { - // output newer location and fail reading - config_path = preferred_path; - events.emit('verbose', 'unable to find ' + config_path); - } else { - config_path = old_config_path; - } - } else { - config_path = preferred_path; - } - var widget_doc = xml_helpers.parseElementtreeSync(config_path); - return widget_doc._root.attrib['id']; - }, - 'source-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) {}, - uninstall: function (obj, project_dir, plugin_id, options) {} - }, - 'header-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) {}, - uninstall: function (obj, project_dir, plugin_id, options) {} - }, - 'resource-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) {}, - uninstall: function (obj, project_dir, plugin_id, options) {} - }, - 'framework': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) {}, - uninstall: function (obj, project_dir, plugin_id, options) {} - }, - 'lib-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) {}, - uninstall: function (obj, project_dir, plugin_id, options) {} - } -}; diff --git a/src/plugman/platforms/ubuntu.js b/src/plugman/platforms/ubuntu.js deleted file mode 100644 index 21b2891e1..000000000 --- a/src/plugman/platforms/ubuntu.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * - * Copyright 2013 Canonical Ltd. - * - * Licensed 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. - * -*/ - -function replaceAt (str, index, char) { - return str.substr(0, index) + char + str.substr(index + char.length); -} - -function toCamelCase (str) { - return str.split('-').map(function (str) { - return replaceAt(str, 0, str[0].toUpperCase()); - }).join(''); -} - -function getPluginXml (plugin_dir) { - var et = require('elementtree'); - var fs = require('fs'); - var path = require('path'); - - var pluginxml; - var config_path = path.join(plugin_dir, 'plugin.xml'); - - if (fs.existsSync(config_path)) { - // Get the current plugin.xml file - pluginxml = et.parse(fs.readFileSync(config_path, 'utf-8')); - } - - return pluginxml; -} - -function findClassName (pluginxml, plugin_id) { - var class_name; - - // first check if we have a class-name parameter in the plugin config - if (pluginxml) { - var platform = pluginxml.find("./platform/[@name='ubuntu']/"); - if (platform) { - var param = platform.find("./config-file/[@target='config.xml']/feature/param/[@name='ubuntu-package']"); - if (param && param.attrib) { - class_name = param.attrib.value; - return class_name; - } - } - } - - // fallback to guess work, based on the plugin package name - - if (plugin_id.match(/\.[^.]+$/)) { - // old-style plugin name (Apache Registry) - class_name = plugin_id.match(/\.[^.]+$/)[0].substr(1); - } else { - // new-style (NPM registry) - var match = plugin_id.match(/cordova\-plugin\-([\w\-]+)$/); // eslint-disable-line no-useless-escape - if (match && match.length > 0) { - class_name = match[0].substr(15); - } else { - // plugins not using a particular naming convention - // and missing a parameter in pluginxml can still - // fallback to using a class name equal to their - // plugin name (in camel case) - class_name = plugin_id; - } - } - - return toCamelCase(class_name); -} - -var shell = require('shelljs'); -var fs = require('fs'); -var path = require('path'); -var common = require('./common'); -var events = require('cordova-common').events; -var xml_helpers = require('cordova-common').xmlHelpers; - -module.exports = { - www_dir: function (project_dir) { - return path.join(project_dir, 'www'); - }, - - package_name: function (project_dir) { - var config_path = path.join(project_dir, 'config.xml'); - var widget_doc = xml_helpers.parseElementtreeSync(config_path); - return widget_doc._root.attrib['id']; - }, - 'source-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - var dest = path.join('build', 'src', 'plugins', plugin_id, path.basename(obj.src)); - common.copyFile(plugin_dir, obj.src, project_dir, dest); - - var cmake = path.join(project_dir, 'build', 'CMakeLists.txt'); - shell.exec('touch ' + cmake); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - var dest = path.join(project_dir, 'build', 'src', 'plugins', plugin_id); - shell.rm(path.join(dest, path.basename(obj.src))); - - var cmake = path.join(project_dir, 'build', 'CMakeLists.txt'); - shell.exec('touch ' + cmake); - } - }, - 'header-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - var dest = path.join('build', 'src', 'plugins', plugin_id, path.basename(obj.src)); - common.copyFile(plugin_dir, obj.src, project_dir, dest); - - var plugins = path.join(project_dir, 'build', 'src', 'coreplugins.cpp'); - var src = String(fs.readFileSync(plugins)); - - src = src.replace('INSERT_HEADER_HERE', '#include "plugins/' + plugin_id + '/' + path.basename(obj.src) + '"\nINSERT_HEADER_HERE'); - - var pluginxml = getPluginXml(plugin_dir); - var class_name = findClassName(pluginxml, plugin_id); - src = src.replace('INSERT_PLUGIN_HERE', 'INIT_PLUGIN(' + class_name + ');INSERT_PLUGIN_HERE'); - - fs.writeFileSync(plugins, src); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - var dest = path.join(project_dir, 'build', 'src', 'plugins', plugin_id); - shell.rm(path.join(dest, path.basename(obj.src))); - - var plugins = path.join(project_dir, 'build', 'src', 'coreplugins.cpp'); - var src = String(fs.readFileSync(plugins)); - - src = src.replace('#include "plugins/' + plugin_id + '/' + path.basename(obj.src) + '"', ''); - var class_name = findClassName(undefined, plugin_id); - src = src.replace('INIT_PLUGIN(' + class_name + ');', ''); - - fs.writeFileSync(plugins, src); - } - }, - 'resource-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - var dest = path.join('qml', path.basename(obj.src)); - if (obj.targetDir) { dest = path.join(obj.targetDir, path.basename(obj.src)); } - common.copyFile(plugin_dir, obj.src, project_dir, dest); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - var dest = path.join(project_dir, 'qml'); - if (obj.targetDir) { dest = path.join(project_dir, obj.targetDir); } - shell.rm(path.join(dest, path.basename(obj.src))); - } - }, - 'framework': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'framework.install is not supported for ubuntu'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'framework.uninstall is not supported for ubuntu'); - } - }, - 'lib-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - events.emit('verbose', 'lib-file.install is not supported for ubuntu'); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - events.emit('verbose', 'lib-file.uninstall is not supported for ubuntu'); - } - } -}; diff --git a/src/plugman/platforms/webos.js b/src/plugman/platforms/webos.js deleted file mode 100755 index ec2b23ff4..000000000 --- a/src/plugman/platforms/webos.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - 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. -*/ - -var path = require('path'); -var common = require('./common'); -var events = require('cordova-common').events; - -module.exports = { - www_dir: function (project_dir) { - return path.join(project_dir, 'www'); - }, - package_name: function (project_dir) { - return common.package_name(project_dir, this.www_dir(project_dir)); - }, - 'source-file': { - install: function (obj, plugin_dir, project_dir, plugin_id, options) { - var dest = path.join(obj.targetDir, path.basename(obj.src)); - common.copyFile(plugin_dir, obj.src, project_dir, dest); - }, - uninstall: function (obj, project_dir, plugin_id, options) { - var dest = path.join(obj.targetDir, path.basename(obj.src)); - common.removeFile(project_dir, dest); - } - }, - 'header-file': { - install: function (source_el, plugin_dir, project_dir, plugin_id) { - events.emit('verbose', 'header-fileinstall is not supported for webos'); - }, - uninstall: function (source_el, project_dir, plugin_id) { - events.emit('verbose', 'header-file.uninstall is not supported for webos'); - } - }, - 'resource-file': { - install: function (el, plugin_dir, project_dir, plugin_id) { - events.emit('verbose', 'resource-file.install is not supported for webos'); - }, - uninstall: function (el, project_dir, plugin_id) { - events.emit('verbose', 'resource-file.uninstall is not supported for webos'); - } - }, - 'framework': { - install: function (source_el, plugin_dir, project_dir, plugin_id) { - events.emit('verbose', 'framework.install is not supported for webos'); - }, - uninstall: function (source_el, project_dir, plugin_id) { - events.emit('verbose', 'framework.uninstall is not supported for webos'); - } - }, - 'lib-file': { - install: function (source_el, plugin_dir, project_dir, plugin_id) { - events.emit('verbose', 'lib-file.install is not supported for webos'); - }, - uninstall: function (source_el, project_dir, plugin_id) { - events.emit('verbose', 'lib-file.uninstall is not supported for webos'); - } - } -}; diff --git a/src/plugman/util/android-project.js b/src/plugman/util/android-project.js deleted file mode 100644 index cdf820deb..000000000 --- a/src/plugman/util/android-project.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - 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. -*/ -/* - Helper for Android projects configuration -*/ - -var fs = require('fs'); -var path = require('path'); -var properties_parser = require('properties-parser'); -var shell = require('shelljs'); - -function addToPropertyList (projectProperties, key, value) { - var i = 1; - while (projectProperties.get(key + '.' + i)) { i++; } - - projectProperties.set(key + '.' + i, value); - projectProperties.dirty = true; -} - -/* eslint-disable no-cond-assign */ -function removeFromPropertyList (projectProperties, key, value) { - var i = 1; - var currentValue; - while (currentValue = projectProperties.get(key + '.' + i)) { - if (currentValue === value) { - while (currentValue = projectProperties.get(key + '.' + (i + 1))) { - projectProperties.set(key + '.' + i, currentValue); - i++; - } - projectProperties.set(key + '.' + i); - break; - } - i++; - } - projectProperties.dirty = true; -} -/* eslint-enable no-cond-assign */ - -function AndroidProject (projectDir) { - this._propertiesEditors = {}; - this._subProjectDirs = {}; - this._dirty = false; - this.projectDir = projectDir; - this.needsSubLibraryUpdate = false; -} - -AndroidProject.prototype = { - addSubProject: function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var subProjectFile = path.resolve(subDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - // TODO: Setting the target needs to happen only for pre-3.7.0 projects - if (fs.existsSync(subProjectFile)) { - var subProperties = this._getPropertiesFile(subProjectFile); - subProperties.set('target', parentProperties.get('target')); - subProperties.dirty = true; - this._subProjectDirs[subDir] = true; - } - addToPropertyList(parentProperties, 'android.library.reference', module.exports.getRelativeLibraryPath(parentDir, subDir)); - - this._dirty = true; - }, - removeSubProject: function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'android.library.reference', module.exports.getRelativeLibraryPath(parentDir, subDir)); - delete this._subProjectDirs[subDir]; - this._dirty = true; - }, - addGradleReference: function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - addToPropertyList(parentProperties, 'cordova.gradle.include', module.exports.getRelativeLibraryPath(parentDir, subDir)); - this._dirty = true; - }, - removeGradleReference: function (parentDir, subDir) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'cordova.gradle.include', module.exports.getRelativeLibraryPath(parentDir, subDir)); - this._dirty = true; - }, - addSystemLibrary: function (parentDir, value) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - addToPropertyList(parentProperties, 'cordova.system.library', value); - this._dirty = true; - }, - removeSystemLibrary: function (parentDir, value) { - var parentProjectFile = path.resolve(parentDir, 'project.properties'); - var parentProperties = this._getPropertiesFile(parentProjectFile); - removeFromPropertyList(parentProperties, 'cordova.system.library', value); - this._dirty = true; - }, - write: function () { - if (!this._dirty) { - return; - } - this._dirty = false; - - for (var filename in this._propertiesEditors) { - var editor = this._propertiesEditors[filename]; - if (editor.dirty) { - // Check for parent directory existence before attempting write - // (when uninstalling a plugin its subprojects' directories are deleted) - if (fs.existsSync(path.dirname(filename))) { - fs.writeFileSync(filename, editor.toString()); - } - editor.dirty = false; - } - } - - // Starting with 3.6.0, the build scripts set ANDROID_HOME, so there is - // no reason to keep run this command. Plus - we really want to avoid - // relying on the presense of native SDKs within plugman. - if (this.needsSubLibraryUpdate) { - for (var sub_dir in this._subProjectDirs) { - shell.exec('android update lib-project --path "' + sub_dir + '"'); - } - } - this._dirty = false; - }, - _getPropertiesFile: function (filename) { - if (!this._propertiesEditors[filename]) { - if (fs.existsSync(filename)) { - this._propertiesEditors[filename] = properties_parser.createEditor(filename); - } else { - this._propertiesEditors[filename] = properties_parser.createEditor(); - } - } - - return this._propertiesEditors[filename]; - } -}; - -module.exports = { - AndroidProject: AndroidProject, - getRelativeLibraryPath: function (parentDir, subDir) { - var libraryPath = path.relative(parentDir, subDir); - return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath; - } -}; diff --git a/src/plugman/util/plist-helpers.js b/src/plugman/util/plist-helpers.js deleted file mode 100644 index 230af9077..000000000 --- a/src/plugman/util/plist-helpers.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - 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. -*/ - -// contains PLIST utility functions -var __ = require('underscore'); -var plist = require('plist'); - -// adds node to doc at selector -module.exports.graftPLIST = graftPLIST; -function graftPLIST (doc, xml, selector) { - var obj = plist.parse('' + xml + ''); - - var node = doc[selector]; - if (node && Array.isArray(node) && Array.isArray(obj)) { - node = node.concat(obj); - for (var i = 0; i < node.length; i++) { - for (var j = i + 1; j < node.length; ++j) { - if (nodeEqual(node[i], node[j])) { node.splice(j--, 1); } - } - } - doc[selector] = node; - } else { - // plist uses objects for . If we have two dicts we merge them instead of - // overriding the old one. See CB-6472 - if (node && __.isObject(node) && __.isObject(obj) && !__.isDate(node) && !__.isDate(obj)) { // arrays checked above - __.extend(obj, node); - } - doc[selector] = obj; - } - - return true; -} - -// removes node from doc at selector -module.exports.prunePLIST = prunePLIST; -function prunePLIST (doc, xml, selector) { - var obj = plist.parse('' + xml + ''); - - pruneOBJECT(doc, selector, obj); - - return true; -} - -function pruneOBJECT (doc, selector, fragment) { - if (Array.isArray(fragment) && Array.isArray(doc[selector])) { - var empty = true; - for (var i in fragment) { - for (var j in doc[selector]) { - empty = pruneOBJECT(doc[selector], j, fragment[i]) && empty; - } - } - if (empty) { - delete doc[selector]; - return true; - } - } else if (nodeEqual(doc[selector], fragment)) { - delete doc[selector]; - return true; - } - - return false; -} - -function nodeEqual (node1, node2) { - if (typeof node1 !== typeof node2) { return false; } else if (typeof node1 === 'string') { - node2 = escapeRE(node2).replace(/\\\$\S+/gm, '(.*?)'); - return new RegExp('^' + node2 + '$').test(node1); - } else { - for (var key in node2) { - if (!nodeEqual(node1[key], node2[key])) return false; - } - return true; - } -} - -// escape string for use in regex -function escapeRE (str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); // eslint-disable-line no-useless-escape -} diff --git a/src/util/windows/csproj.js b/src/util/windows/csproj.js deleted file mode 100644 index 51efb5f3f..000000000 --- a/src/util/windows/csproj.js +++ /dev/null @@ -1,177 +0,0 @@ -/** - 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. -*/ - -var xml_helpers = require('cordova-common').xmlHelpers; -var et = require('elementtree'); -var fs = require('fs'); -var path = require('path'); - -function csproj (location) { - this.location = location; - this.xml = xml_helpers.parseElementtreeSync(location); - return this; -} - -csproj.prototype = { - write: function () { - fs.writeFileSync(this.location, this.xml.write({indent: 4}), 'utf-8'); - }, - // add/remove the item group for SDKReference - // example : - // - addSDKRef: function (incText) { - var item_group = new et.Element('ItemGroup'); - var elem = new et.Element('SDKReference'); - elem.attrib.Include = incText; - - item_group.append(elem); - this.xml.getroot().append(item_group); - }, - - removeSDKRef: function (incText) { - var item_group = this.xml.find('ItemGroup/SDKReference[@Include="' + incText + '"]/..'); - if (item_group) { - this.xml.getroot().remove(item_group); - } - }, - addReference: function (relPath) { - var item = new et.Element('ItemGroup'); - var extName = path.extname(relPath); - - var elem = new et.Element('Reference'); - // add dll file name - elem.attrib.Include = path.basename(relPath, extName); - // add hint path with full path - var hint_path = new et.Element('HintPath'); - hint_path.text = relPath; - elem.append(hint_path); - - if (extName === '.winmd') { - var mdFileTag = new et.Element('IsWinMDFile'); - mdFileTag.text = 'true'; - elem.append(mdFileTag); - } - - item.append(elem); - - this.xml.getroot().append(item); - }, - - removeReference: function (relPath) { - var extName = path.extname(relPath); - var includeText = path.basename(relPath, extName); - // - // - var item_groups = this.xml.findall('ItemGroup/Reference[@Include="' + includeText + '"]/..'); - - if (item_groups.length > 0) { - this.xml.getroot().remove(item_groups[0]); - } - }, - - addSourceFile: function (relative_path) { - // we allow multiple paths to be passed at once as array so that - // we don't create separate ItemGroup for each source file, CB-6874 - if (!(relative_path instanceof Array)) { - relative_path = [relative_path]; - } - var compile; - // make ItemGroup to hold file. - var item = new et.Element('ItemGroup'); - var me = this; - relative_path.forEach(function (filePath) { - - filePath = filePath.split('/').join('\\'); - var extName = path.extname(filePath); - // check if it's a .xaml page - if (extName === '.xaml') { - var page = new et.Element('Page'); - var sub_type = new et.Element('SubType'); - - sub_type.text = 'Designer'; - page.append(sub_type); - page.attrib.Include = filePath; - - var gen = new et.Element('Generator'); - gen.text = 'MSBuild:Compile'; - page.append(gen); - var item_groups = me.xml.findall('ItemGroup'); - if (item_groups.length === 0) { - item.append(page); - } else { - item_groups[0].append(page); - } - - } else if (extName === '.cs') { - compile = new et.Element('Compile'); - compile.attrib.Include = filePath; - // check if it's a .xaml.cs page that would depend on a .xaml of the same name - if (filePath.indexOf('.xaml.cs', filePath.length - 8) > -1) { - var dep = new et.Element('DependentUpon'); - var parts = filePath.split('\\'); - var xaml_file = parts[parts.length - 1].substr(0, parts[parts.length - 1].length - 3); // Benn, really !? - dep.text = xaml_file; - compile.append(dep); - } - item.append(compile); - } else { // otherwise add it normally - compile = new et.Element('Content'); - compile.attrib.Include = filePath; - item.append(compile); - } - }); - this.xml.getroot().append(item); - }, - - removeSourceFile: function (relative_path) { - var isRegexp = relative_path instanceof RegExp; - - if (!isRegexp) { - // path.normalize(relative_path);// ?? - relative_path = relative_path.split('/').join('\\'); - } - - var root = this.xml.getroot(); - // iterate through all ItemGroup/Content elements and remove all items matched - this.xml.findall('ItemGroup').forEach(function (group) { - // matched files in current ItemGroup - var filesToRemove = group.findall('Compile').concat(group.findall('Page')) - .concat(group.findall('Content')).filter(function (item) { - if (!item.attrib.Include) return false; - return isRegexp ? item.attrib.Include.match(relative_path) : - item.attrib.Include === relative_path; - }); - - // nothing to remove, skip.. - if (filesToRemove.length < 1) return; - - filesToRemove.forEach(function (file) { - // remove file reference - group.remove(file); - }); - - // remove ItemGroup if empty - if (group.findall('*').length < 1) { - root.remove(group); - } - }); - } -}; - -module.exports = csproj; diff --git a/src/util/windows/jsprojManager.js b/src/util/windows/jsprojManager.js deleted file mode 100644 index c0aec6847..000000000 --- a/src/util/windows/jsprojManager.js +++ /dev/null @@ -1,588 +0,0 @@ -/** - 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. - */ - -/* - Helper for dealing with Windows Store JS app .jsproj files - */ - -var util = require('util'); -var xml_helpers = require('cordova-common').xmlHelpers; -var et = require('elementtree'); -var fs = require('fs'); -var glob = require('glob'); -var shell = require('shelljs'); -var events = require('cordova-common').events; -var path = require('path'); -var semver = require('semver'); - -var WinCSharpProjectTypeGUID = '{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}'; // .csproj -var WinCplusplusProjectTypeGUID = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}'; // .vcxproj - -/* eslint-disable no-useless-escape */ - -// Match a JavaScript Project -var JsProjectRegEx = /(Project\("\{262852C6-CD72-467D-83FE-5EEB1973A190}"\)\s*=\s*"[^"]+",\s*"[^"]+",\s*"\{[0-9a-f\-]+}"[^\r\n]*[\r\n]*)/gi; - -// Chars in a string that need to be escaped when used in a RegExp -var RegExpEscRegExp = /([.?*+\^$\[\]\\(){}|\-])/g; - -function jsprojManager (location) { - this.isUniversalWindowsApp = path.extname(location).toLowerCase() === '.projitems'; - this.projects = []; - this.master = this.isUniversalWindowsApp ? new proj(location) : new jsproj(location); // eslint-disable-line new-cap - this.projectFolder = path.dirname(location); -} -/* eslint-enable no-useless-escape */ - -function getProjectName (pluginProjectXML, relative_path) { - var projNameElt = pluginProjectXML.find('PropertyGroup/ProjectName'); - // Falling back on project file name in case ProjectName is missing - return projNameElt ? projNameElt.text : path.basename(relative_path, path.extname(relative_path)); -} - -jsprojManager.prototype = { - _projects: null, - - write: function () { - this.master.write(); - if (this._projects) { - var that = this; - this._projects.forEach(function (project) { - if (project !== that.master && project.touched) { - project.write(); - } - }); - } - }, - - addSDKRef: function (incText, targetConditions) { - events.emit('verbose', 'jsprojManager.addSDKRef(incText: ' + incText + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - var item = createItemGroupElement('ItemGroup/SDKReference', incText, targetConditions); - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.appendToRoot(item); - }); - }, - - removeSDKRef: function (incText, targetConditions) { - events.emit('verbose', 'jsprojManager.removeSDKRef(incText: ' + incText + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.removeItemGroupElement('ItemGroup/SDKReference', incText, targetConditions); - }); - }, - - addResourceFileToProject: function (relPath, targetConditions) { - events.emit('verbose', 'jsprojManager.addResourceFile(relPath: ' + relPath + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - // add hint path with full path - var link = new et.Element('Link'); - link.text = relPath; - var children = [link]; - - var copyToOutputDirectory = new et.Element('CopyToOutputDirectory'); - copyToOutputDirectory.text = 'Always'; - children.push(copyToOutputDirectory); - - var item = createItemGroupElement('ItemGroup/Content', relPath, targetConditions, children); - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.appendToRoot(item); - }); - }, - - removeResourceFileFromProject: function (relPath, targetConditions) { - events.emit('verbose', 'jsprojManager.removeResourceFile(relPath: ' + relPath + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.removeItemGroupElement('ItemGroup/Content', relPath, targetConditions); - }); - }, - - addReference: function (relPath, targetConditions) { - events.emit('verbose', 'jsprojManager.addReference(incText: ' + relPath + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - // add hint path with full path - var hint_path = new et.Element('HintPath'); - hint_path.text = relPath; - var children = [hint_path]; - - var extName = path.extname(relPath); - if (extName === '.winmd') { - var mdFileTag = new et.Element('IsWinMDFile'); - mdFileTag.text = 'true'; - children.push(mdFileTag); - } - - var item = createItemGroupElement('ItemGroup/Reference', path.basename(relPath, extName), targetConditions, children); - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.appendToRoot(item); - }); - - }, - - removeReference: function (relPath, targetConditions) { - events.emit('verbose', 'jsprojManager.removeReference(incText: ' + relPath + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - var extName = path.extname(relPath); - var includeText = path.basename(relPath, extName); - - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.removeItemGroupElement('ItemGroup/Reference', includeText, targetConditions); - }); - }, - - addSourceFile: function (relative_path) { - events.emit('verbose', 'jsprojManager.addSourceFile(relative_path: ' + relative_path + ')'); - this.master.addSourceFile(relative_path); - }, - - removeSourceFile: function (relative_path) { - events.emit('verbose', 'jsprojManager.removeSourceFile(incText: ' + relative_path + ')'); - this.master.removeSourceFile(relative_path); - }, - - addProjectReference: function (relative_path, targetConditions) { - events.emit('verbose', 'jsprojManager.addProjectReference(incText: ' + relative_path + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - // relative_path is the actual path to the file in the current OS, where-as inserted_path is what we write in - // the project file, and is always in Windows format. - relative_path = path.normalize(relative_path); - var inserted_path = relative_path.split('/').join('\\'); - - var pluginProjectXML = xml_helpers.parseElementtreeSync(relative_path); - - // find the guid + name of the referenced project - var projectGuid = pluginProjectXML.find('PropertyGroup/ProjectGuid').text; - var projName = getProjectName(pluginProjectXML, relative_path); - - // get the project type - var projectTypeGuid = getProjectTypeGuid(relative_path); - if (!projectTypeGuid) { - throw new Error('unrecognized project type'); - } - - var preInsertText = '\tProjectSection(ProjectDependencies) = postProject\r\n' + - '\t\t' + projectGuid + '=' + projectGuid + '\r\n' + - '\tEndProjectSection\r\n'; - var postInsertText = '\r\nProject("' + projectTypeGuid + '") = "' + - projName + '", "' + inserted_path + '", ' + - '"' + projectGuid + '"\r\nEndProject'; - - var matchingProjects = this._getMatchingProjects(targetConditions); - if (matchingProjects.length === 0) { - // No projects meet the specified target and version criteria, so nothing to do. - return; - } - - // Will we be writing into the .projitems file rather than individual .jsproj files? - var useProjItems = this.isUniversalWindowsApp && matchingProjects.length === 1 && matchingProjects[0] === this.master; - - // There may be multiple solution files (for different VS versions) - process them all - getSolutionPaths(this.projectFolder).forEach(function (solutionPath) { - var solText = fs.readFileSync(solutionPath, {encoding: 'utf8'}); - - if (useProjItems) { - // Insert a project dependency into every jsproj in the solution. - var jsProjectFound = false; - solText = solText.replace(JsProjectRegEx, function (match) { - jsProjectFound = true; - return match + preInsertText; - }); - - if (!jsProjectFound) { - throw new Error('no jsproj found in solution'); - } - } else { - // Insert a project dependency only for projects that match specified target and version - matchingProjects.forEach(function (project) { - solText = solText.replace(getJsProjRegExForProject(path.basename(project.location)), function (match) { - return match + preInsertText; - }); - }); - } - - // Add the project after existing projects. Note that this fairly simplistic check should be fine, since the last - // EndProject in the file should actually be an EndProject (and not an EndProjectSection, for example). - var pos = solText.lastIndexOf('EndProject'); - if (pos === -1) { - throw new Error('no EndProject found in solution'); - } - pos += 10; // Move pos to the end of EndProject text - solText = solText.slice(0, pos) + postInsertText + solText.slice(pos); - - fs.writeFileSync(solutionPath, solText, {encoding: 'utf8'}); - }); - - // Add the ItemGroup/ProjectReference to each matching cordova project : - // - var item = createItemGroupElement('ItemGroup/ProjectReference', inserted_path, targetConditions); - matchingProjects.forEach(function (project) { - project.appendToRoot(item); - }); - }, - - removeProjectReference: function (relative_path, targetConditions) { - events.emit('verbose', 'jsprojManager.removeProjectReference(incText: ' + relative_path + ', targetConditions: ' + JSON.stringify(targetConditions) + ')'); - - // relative_path is the actual path to the file in the current OS, where-as inserted_path is what we write in - // the project file, and is always in Windows format. - relative_path = path.normalize(relative_path); - var inserted_path = relative_path.split('/').join('\\'); - - // find the guid + name of the referenced project - var pluginProjectXML = xml_helpers.parseElementtreeSync(relative_path); - var projectGuid = pluginProjectXML.find('PropertyGroup/ProjectGuid').text; - var projName = getProjectName(pluginProjectXML, relative_path); - - // get the project type - var projectTypeGuid = getProjectTypeGuid(relative_path); - if (!projectTypeGuid) { - throw new Error('unrecognized project type'); - } - - var preInsertTextRegExp = getProjectReferencePreInsertRegExp(projectGuid); - var postInsertTextRegExp = getProjectReferencePostInsertRegExp(projName, projectGuid, inserted_path, projectTypeGuid); - - // There may be multiple solutions (for different VS versions) - process them all - getSolutionPaths(this.projectFolder).forEach(function (solutionPath) { - var solText = fs.readFileSync(solutionPath, {encoding: 'utf8'}); - - // To be safe (to handle subtle changes in formatting, for example), use a RegExp to find and remove - // preInsertText and postInsertText - - solText = solText.replace(preInsertTextRegExp, function () { - return ''; - }); - - solText = solText.replace(postInsertTextRegExp, function () { - return ''; - }); - - fs.writeFileSync(solutionPath, solText, {encoding: 'utf8'}); - }); - - this._getMatchingProjects(targetConditions).forEach(function (project) { - project.removeItemGroupElement('ItemGroup/ProjectReference', inserted_path, targetConditions); - }); - }, - - _getMatchingProjects: function (targetConditions) { - // If specified, target can be 'all' (default), 'phone' or 'windows'. Ultimately should probably allow a comma - // separated list, but not needed now. - var target = getDeviceTarget(targetConditions); - var versions = getVersions(targetConditions); - - if (target || versions) { - var matchingProjects = this.projects.filter(function (project) { - return (!target || target === project.target) && - (!versions || semver.satisfies(project.getSemVersion(), versions, /* loose */ true)); - }); - - if (matchingProjects.length < this.projects.length) { - return matchingProjects; - } - } - - // All projects match. If this is a universal project, return the projitems file. Otherwise return our single - // project. - return [this.master]; - }, - - get projects () { - var projects = this._projects; - if (!projects) { - projects = []; - this._projects = projects; - - if (this.isUniversalWindowsApp) { - var projectPath = this.projectFolder; - var projectFiles = glob.sync('*.jsproj', {cwd: projectPath}); - projectFiles.forEach(function (projectFile) { - projects.push(new jsproj(path.join(projectPath, projectFile))); // eslint-disable-line new-cap - }); - } else { - this.projects.push(this.master); - } - } - - return projects; - } -}; - -function getProjectReferencePreInsertRegExp (projectGuid) { - projectGuid = escapeRegExpString(projectGuid); - return new RegExp('\\s*ProjectSection\\(ProjectDependencies\\)\\s*=\\s*postProject\\s*' + projectGuid + '\\s*=\\s*' + projectGuid + '\\s*EndProjectSection', 'gi'); -} - -function getProjectReferencePostInsertRegExp (projName, projectGuid, relative_path, projectTypeGuid) { - projName = escapeRegExpString(projName); - projectGuid = escapeRegExpString(projectGuid); - relative_path = escapeRegExpString(relative_path); - projectTypeGuid = escapeRegExpString(projectTypeGuid); - return new RegExp('\\s*Project\\("' + projectTypeGuid + '"\\)\\s*=\\s*"' + projName + '"\\s*,\\s*"' + relative_path + '"\\s*,\\s*"' + projectGuid + '"\\s*EndProject', 'gi'); -} - -function getSolutionPaths (projectFolder) { - return shell.ls(path.join(projectFolder, '*.sln')); // TODO:error handling -} - -function escapeRegExpString (regExpString) { - return regExpString.replace(RegExpEscRegExp, '\\$1'); -} - -function getJsProjRegExForProject (projectFile) { - projectFile = escapeRegExpString(projectFile); - return new RegExp('(Project\\("\\{262852C6-CD72-467D-83FE-5EEB1973A190}"\\)\\s*=\\s*"[^"]+",\\s*"' + projectFile + '",\\s*"\\{[0-9a-f\\-]+}"[^\\r\\n]*[\\r\\n]*)', 'gi'); -} - -function getProjectTypeGuid (projectPath) { - switch (path.extname(projectPath)) { - case '.vcxproj': - return WinCplusplusProjectTypeGUID; - - case '.csproj': - return WinCSharpProjectTypeGUID; - } - return null; -} - -function createItemGroupElement (path, incText, targetConditions, children) { - path = path.split('/'); - path.reverse(); - - var lastElement = null; - path.forEach(function (elementName) { - var element = new et.Element(elementName); - if (lastElement) { - element.append(lastElement); - } else { - element.attrib.Include = incText; - - var condition = createConditionAttrib(targetConditions); - if (condition) { - element.attrib.Condition = condition; - } - - if (children) { - children.forEach(function (child) { - element.append(child); - }); - } - } - lastElement = element; - }); - - return lastElement; -} - -function getDeviceTarget (targetConditions) { - var target = targetConditions.deviceTarget; - if (target) { - target = target.toLowerCase().trim(); - if (target === 'all') { - target = null; - } else if (target === 'win') { - // Allow "win" as alternative to "windows" - target = 'windows'; - } else if (target !== 'phone' && target !== 'windows') { - throw new Error('Invalid device-target attribute (must be "all", "phone", "windows" or "win"): ' + target); - } - } - return target; -} - -function getVersions (targetConditions) { - var versions = targetConditions.versions; - if (versions && !semver.validRange(versions, /* loose */ true)) { - throw new Error('Invalid versions attribute (must be a valid semantic version range): ' + versions); - } - return versions; -} - -/* proj */ - -function proj (location) { - // Class to handle simple project xml operations - if (!location) { - throw new Error('Project file location can\'t be null or empty'); - } - this.location = location; - this.xml = xml_helpers.parseElementtreeSync(location); -} - -proj.prototype = { - write: function () { - fs.writeFileSync(this.location, this.xml.write({indent: 4}), 'utf-8'); - }, - - appendToRoot: function (element) { - this.touched = true; - this.xml.getroot().append(element); - }, - - removeItemGroupElement: function (path, incText, targetConditions) { - var xpath = path + '[@Include="' + incText + '"]'; - var condition = createConditionAttrib(targetConditions); - if (condition) { - xpath += '[@Condition="' + condition + '"]'; - } - xpath += '/..'; - - var itemGroup = this.xml.find(xpath); - if (itemGroup) { - this.touched = true; - this.xml.getroot().remove(itemGroup); - } - }, - - addSourceFile: function (relative_path) { - // we allow multiple paths to be passed at once as array so that - // we don't create separate ItemGroup for each source file, CB-6874 - if (!(relative_path instanceof Array)) { - relative_path = [relative_path]; - } - - // make ItemGroup to hold file. - var item = new et.Element('ItemGroup'); - - relative_path.forEach(function (filePath) { - // filePath is never used to find the actual file - it determines what we write to the project file, and so - // should always be in Windows format. - filePath = filePath.split('/').join('\\'); - - var content = new et.Element('Content'); - content.attrib.Include = filePath; - item.append(content); - }); - - this.appendToRoot(item); - }, - - removeSourceFile: function (relative_path) { - var isRegexp = relative_path instanceof RegExp; - if (!isRegexp) { - // relative_path is never used to find the actual file - it determines what we write to the project file, - // and so should always be in Windows format. - relative_path = relative_path.split('/').join('\\'); - } - - var root = this.xml.getroot(); - var that = this; - // iterate through all ItemGroup/Content elements and remove all items matched - this.xml.findall('ItemGroup').forEach(function (group) { - // matched files in current ItemGroup - var filesToRemove = group.findall('Content').filter(function (item) { - if (!item.attrib.Include) { - return false; - } - return isRegexp ? item.attrib.Include.match(relative_path) : item.attrib.Include === relative_path; - }); - - // nothing to remove, skip.. - if (filesToRemove.length < 1) { - return; - } - - filesToRemove.forEach(function (file) { - // remove file reference - group.remove(file); - }); - // remove ItemGroup if empty - if (group.findall('*').length < 1) { - that.touched = true; - root.remove(group); - } - }); - } -}; - -/* jsproj */ - -function jsproj (location) { - function targetPlatformIdentifierToDevice (jsprojPlatform) { - var index = ['Windows', 'WindowsPhoneApp', 'UAP'].indexOf(jsprojPlatform); - if (index < 0) { - throw new Error("Unknown TargetPlatformIdentifier '" + jsprojPlatform + "' in project file '" + location + "'"); - } - return ['windows', 'phone', 'windows'][index]; - } - - function validateVersion (version) { - version = version.split('.'); - while (version.length < 3) { - version.push('0'); - } - return version.join('.'); - } - - // Class to handle a jsproj file - proj.call(this, location); - - var propertyGroup = this.xml.find('PropertyGroup[TargetPlatformIdentifier]'); - if (!propertyGroup) { - throw new Error("Unable to find PropertyGroup/TargetPlatformIdentifier in project file '" + this.location + "'"); - } - - var jsprojPlatform = propertyGroup.find('TargetPlatformIdentifier').text; - this.target = targetPlatformIdentifierToDevice(jsprojPlatform); - - var version = propertyGroup.find('TargetPlatformVersion'); - if (!version) { - throw new Error("Unable to find PropertyGroup/TargetPlatformVersion in project file '" + this.location + "'"); - } - this.version = validateVersion(version.text); -} - -util.inherits(jsproj, proj); - -jsproj.prototype.target = null; -jsproj.prototype.version = null; - -// Returns valid semantic version (http://semver.org/). -jsproj.prototype.getSemVersion = function () { - // For example, for version 10.0.10240.0 we will return 10.0.10240 (first three components) - var semVersion = this.version; - var splittedVersion = semVersion.split('.'); - if (splittedVersion.length > 3) { - semVersion = splittedVersion.splice(0, 3).join('.'); - } - - return semVersion; - // Alternative approach could be replacing last dot with plus sign to - // be complaint w/ semver specification, for example - // 10.0.10240.0 -> 10.0.10240+0 -}; - -/* Common support functions */ - -function createConditionAttrib (targetConditions) { - var arch = targetConditions.arch; - if (arch) { - if (arch === 'arm') { - // Specifcally allow "arm" as alternative to "ARM" - arch = 'ARM'; - } else if (arch !== 'x86' && arch !== 'x64' && arch !== 'ARM') { - throw new Error('Invalid arch attribute (must be "x86", "x64" or "ARM"): ' + arch); - } - return "'$(Platform)'=='" + arch + "'"; - } - return null; -} - -module.exports = jsprojManager;