You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by er...@apache.org on 2025/07/15 05:43:10 UTC
(cordova-common) branch master updated: feat: Support finding an unprefixed Info.plist file (#212)
This is an automated email from the ASF dual-hosted git repository.
erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-common.git
The following commit(s) were added to refs/heads/master by this push:
new 30206cd feat: Support finding an unprefixed Info.plist file (#212)
30206cd is described below
commit 30206cdc2642758f20291450ac05d8b08836d61f
Author: Darryl Pogue <da...@dpogue.ca>
AuthorDate: Mon Jul 14 22:43:06 2025 -0700
feat: Support finding an unprefixed Info.plist file (#212)
Co-authored-by: Norman Breau <no...@nbsolutions.ca>
---
package-lock.json | 55 -------------------
package.json | 1 -
spec/ConfigChanges/ConfigChanges.spec.js | 2 +-
spec/ConfigChanges/ConfigFile.spec.js | 42 ++++++++-------
src/ConfigChanges/ConfigFile.js | 93 ++++++++++++++++++--------------
5 files changed, 76 insertions(+), 117 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 6aa062a..d426883 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,7 +18,6 @@
"fast-glob": "^3.3.3",
"plist": "^3.1.0",
"q": "^1.5.1",
- "read-chunk": "^3.2.0",
"strip-bom": "^4.0.0"
},
"devDependencies": {
@@ -3239,15 +3238,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -3280,15 +3270,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -3374,15 +3355,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/plist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
@@ -3458,19 +3430,6 @@
],
"license": "MIT"
},
- "node_modules/read-chunk": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz",
- "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==",
- "license": "MIT",
- "dependencies": {
- "pify": "^4.0.1",
- "with-open-file": "^0.1.6"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -4630,20 +4589,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/with-open-file": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz",
- "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==",
- "license": "MIT",
- "dependencies": {
- "p-finally": "^1.0.0",
- "p-try": "^2.1.0",
- "pify": "^4.0.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
diff --git a/package.json b/package.json
index eae4271..fcbe238 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,6 @@
"fast-glob": "^3.3.3",
"plist": "^3.1.0",
"q": "^1.5.1",
- "read-chunk": "^3.2.0",
"strip-bom": "^4.0.0"
},
"devDependencies": {
diff --git a/spec/ConfigChanges/ConfigChanges.spec.js b/spec/ConfigChanges/ConfigChanges.spec.js
index 6085591..ccaee9f 100644
--- a/spec/ConfigChanges/ConfigChanges.spec.js
+++ b/spec/ConfigChanges/ConfigChanges.spec.js
@@ -508,7 +508,7 @@ describe('config-changes module', function () {
const munger = new configChanges.PlatformMunger('ios', temp, platformJson, pluginInfoProvider);
munger.process(plugins_dir);
- expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf8');
+ expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'));
});
it('Test 026 : should move successfully installed plugins from queue to installed plugins section, and include/retain vars if applicable', function () {
diff --git a/spec/ConfigChanges/ConfigFile.spec.js b/spec/ConfigChanges/ConfigFile.spec.js
index c5e7958..1aa60a6 100644
--- a/spec/ConfigChanges/ConfigFile.spec.js
+++ b/spec/ConfigChanges/ConfigFile.spec.js
@@ -15,17 +15,11 @@
under the License.
*/
-const rewire = require('rewire');
const fs = require('node:fs');
const path = require('node:path');
-const readChunk = require('read-chunk');
+const ConfigFile = require('../../src/ConfigChanges/ConfigFile');
describe('ConfigFile tests', function () {
- let ConfigFile;
- beforeEach(() => {
- ConfigFile = rewire('../../src/ConfigChanges/ConfigFile');
- });
-
describe('instance methods', () => {
describe('save', () => {
it('calls fs.writeFileSync', function () {
@@ -37,18 +31,6 @@ describe('ConfigFile tests', function () {
});
describe('static methods', () => {
- describe('isBinaryPlist', () => {
- it('should return false if not binary', function () {
- spyOn(readChunk, 'sync').and.returnValue('not bplist');
- expect(ConfigFile.isBinaryPlist('someFile')).toBe(false);
- });
-
- it('should return true if binary', function () {
- spyOn(readChunk, 'sync').and.returnValue('bplist');
- expect(ConfigFile.isBinaryPlist('someFile')).toBe(true);
- });
- });
-
describe('getIOSProjectname', () => {
it('should throw error', function () {
expect(function () { ConfigFile.getIOSProjectname('some/project/name'); }).toThrow();
@@ -78,6 +60,11 @@ describe('ConfigFile tests', function () {
expect(ConfigFile.resolveConfigFilePath('project_dir', 'android', 'strings.xml')).toBe(stringsPath);
});
+ it('should return android values xml file path', function () {
+ const resPath = path.join(projectDir, 'res', 'values', 'colors.xml');
+ expect(ConfigFile.resolveConfigFilePath('project_dir', 'android', path.join('res', 'values', 'colors.xml'))).toBe(resPath);
+ });
+
it('should return ios config.xml file path', function () {
spyOn(ConfigFile, 'getIOSProjectname').and.returnValue('iospath');
const configPath = path.join('project_dir', 'iospath', 'config.xml');
@@ -106,7 +93,7 @@ describe('ConfigFile tests', function () {
const projName = 'XXX';
const expectedPlistPath = `${projName}${path.sep}${projName}-Info.plist`;
- ConfigFile.__set__('getIOSProjectname', () => projName);
+ spyOn(ConfigFile, 'getIOSProjectname').and.returnValue(projName);
spyOn(require('fast-glob'), 'sync').and.returnValue([
`AAA/${projName}-Info.plist`,
`Pods/Target Support Files/Pods-${projName}/Info.plist`,
@@ -116,6 +103,21 @@ describe('ConfigFile tests', function () {
expect(ConfigFile.resolveConfigFilePath('', 'ios', '*-Info.plist')).toBe(expectedPlistPath);
});
+
+ it('should return Info.plist file', function () {
+ const projName = 'XXX';
+ const expectedPlistPath = path.join(projName, 'Info.plist');
+
+ spyOn(ConfigFile, 'getIOSProjectname').and.returnValue(projName);
+ spyOn(require('fast-glob'), 'sync').and.returnValue([
+ 'AAA/Info.plist',
+ `Pods/Target Support Files/Pods-${projName}/Info.plist`,
+ `Pods/Target Support Files/Pods-${projName}/Pods-${projName}-Info.plist`,
+ expectedPlistPath
+ ]);
+
+ expect(ConfigFile.resolveConfigFilePath('', 'ios', '*-Info.plist')).toBe(expectedPlistPath);
+ });
});
});
});
diff --git a/src/ConfigChanges/ConfigFile.js b/src/ConfigChanges/ConfigFile.js
index bc2673c..dfbf299 100644
--- a/src/ConfigChanges/ConfigFile.js
+++ b/src/ConfigChanges/ConfigFile.js
@@ -16,7 +16,6 @@
const fs = require('node:fs');
const path = require('node:path');
-const readChunk = require('read-chunk');
// Use delay loading to ensure plist and other node modules to not get loaded
// on Android, Windows platforms
@@ -29,6 +28,9 @@ const modules = {
get xml_helpers () { return require('../util/xml-helpers'); }
};
+// Cache of project folder paths to Xcode project names
+const xcodeprojMap = new Map();
+
/******************************************************************************
* ConfigFile class
*
@@ -73,13 +75,13 @@ class ConfigFile {
} else {
// plist file
this.type = 'plist';
- // TODO: isBinaryPlist() reads the file and then parse re-reads it again.
- // We always write out text plist, not binary.
- // Do we still need to support binary plist?
- // If yes, use plist.parseStringSync() and read the file once.
- this.data = isBinaryPlist(filepath)
- ? modules.bplist.parseBuffer(fs.readFileSync(filepath))[0]
- : modules.plist.parse(fs.readFileSync(filepath, 'utf8'));
+
+ const fileData = fs.readFileSync(filepath);
+ if (fileData.toString('utf8', 0, 6) === 'bplist') {
+ this.data = modules.bplist.parseBuffer(fileData)[0];
+ } else {
+ this.data = modules.plist.parse(fileData.toString('utf8'));
+ }
}
}
@@ -154,11 +156,34 @@ class ConfigFile {
this.is_changed = true;
}
+
+ // Find out the real name of an iOS project
+ //
+ // This caches the project name for a given directory path, assuming that
+ // it won't change over the course of a single Cordova command invocation
+ static getIOSProjectname (project_dir) {
+ if (xcodeprojMap.has(project_dir)) {
+ return xcodeprojMap.get(project_dir);
+ }
+
+ const matches = modules.glob.sync('*.xcodeproj', { cwd: project_dir, onlyDirectories: true });
+
+ if (matches.length !== 1) {
+ const msg = matches.length === 0
+ ? 'Does not appear to be an xcode project, no xcode project file'
+ : 'There are multiple *.xcodeproj dirs';
+
+ throw new Error(`${msg} in ${project_dir}`);
+ }
+
+ const projectName = path.basename(matches[0], '.xcodeproj');
+ xcodeprojMap.set(project_dir, projectName);
+ return projectName;
+ }
}
// Some config-file target attributes are not qualified with a full leading directory, or contain wildcards.
// Resolve to a real path in this function.
-// TODO: getIOSProjectname is slow because of glob, try to avoid calling it several times per project.
function resolveConfigFilePath (project_dir, platform, file) {
let filepath = path.join(project_dir, file);
let matches;
@@ -167,20 +192,32 @@ function resolveConfigFilePath (project_dir, platform, file) {
if (file.includes('*')) {
// handle wildcards in targets using glob.
- matches = modules.glob.sync(`**/${file}`, {
+ matches = modules.glob.sync(`**/${file.replace('*-Info.plist', '*Info.plist')}`, {
fs,
cwd: project_dir,
absolute: true
}).map(path.normalize);
- if (matches.length) filepath = matches[0];
+ if (matches.length) {
+ filepath = matches[0];
+ }
- // [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
+ // [CB-5989] multiple Info.plist files may exist. default to Info.plist then $PROJECT_NAME-Info.plist
if (matches.length > 1 && file.includes('-Info.plist')) {
- const projName = getIOSProjectname(project_dir);
+ const projName = ConfigFile.getIOSProjectname(project_dir);
+
+ // Try to find a unprefix Info.plist file first
+ let plistPath = path.join(project_dir, projName, 'Info.plist');
+ if (matches.includes(plistPath)) {
+ return plistPath;
+ }
+
+ // Then try to find one prefixed with the project name
const plistName = `${projName}-Info.plist`;
- const plistPath = path.join(project_dir, projName, plistName);
- if (matches.includes(plistPath)) return plistPath;
+ plistPath = path.join(project_dir, projName, plistName);
+ if (matches.includes(plistPath)) {
+ return plistPath;
+ }
}
return filepath;
}
@@ -216,7 +253,7 @@ function resolveConfigFilePath (project_dir, platform, file) {
if (platform === 'ios' || platform === 'osx') {
filepath = path.join(
project_dir,
- module.exports.getIOSProjectname(project_dir),
+ ConfigFile.getIOSProjectname(project_dir),
'config.xml'
);
} else {
@@ -235,29 +272,5 @@ function resolveConfigFilePath (project_dir, platform, file) {
return filepath;
}
-// Find out the real name of an iOS or OSX project
-// TODO: glob is slow, need a better way or caching, or avoid using more than once.
-function getIOSProjectname (project_dir) {
- const matches = modules.glob.sync('*.xcodeproj', { cwd: project_dir, onlyDirectories: true });
-
- if (matches.length !== 1) {
- const msg = matches.length === 0
- ? 'Does not appear to be an xcode project, no xcode project file'
- : 'There are multiple *.xcodeproj dirs';
-
- throw new Error(`${msg} in ${project_dir}`);
- }
-
- return path.basename(matches[0], '.xcodeproj');
-}
-
-// determine if a plist file is binary
-// i.e. they start with the magic header "bplist"
-function isBinaryPlist (filename) {
- return readChunk.sync(filename, 0, 6).toString() === 'bplist';
-}
-
module.exports = ConfigFile;
-module.exports.isBinaryPlist = isBinaryPlist;
-module.exports.getIOSProjectname = getIOSProjectname;
module.exports.resolveConfigFilePath = resolveConfigFilePath;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org