Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use new provisioning profile directory for lookup #244

Merged
merged 7 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ exports.findValidDeviceCertProfileCombos = findValidDeviceCertProfileCombos;
* @param {Boolean} [options.bypassCache=false] - When true, re-detects the all iOS information.
* @param {String} [options.minIosVersion] - The minimum iOS SDK to detect.
* @param {String} [options.minWatchosVersion] - The minimum WatchOS SDK to detect.
* @param {String} [options.profileDir=~/Library/MobileDevice/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {String} [options.profileDir=~/Library/Developer/Xcode/UserData/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {String} [options.security] - Path to the <code>security</code> executable
* @param {String} [options.supportedVersions] - A string with a version number or range to check if an Xcode install is supported.
* @param {String} [options.type] - The type of emulators to return. Can be either "iphone" or "ipad". Defaults to all types.
Expand Down
147 changes: 89 additions & 58 deletions lib/provisioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ const
fs = require('fs'),
path = require('path'),
__ = appc.i18n(__dirname).__,
defaultProfileDir = '~/Library/MobileDevice/Provisioning Profiles';
provisioningProfilesDirectories = [
'~/Library/Developer/Xcode/UserData/Provisioning Profiles',
'~/Library/MobileDevice/Provisioning Profiles'
]

var cache = null,
watchers = {};
Expand All @@ -37,7 +40,6 @@ var cache = null,
* @type {Error}
*/

exports.defaultProfileDir = defaultProfileDir;
exports.detect = detect;
exports.find = find;
exports.watch = watch;
Expand All @@ -48,7 +50,7 @@ exports.unwatch = unwatch;
*
* @param {Object} [options] - An object containing various settings.
* @param {Boolean} [options.bypassCache=false] - When true, re-detects all provisioning profiles.
* @param {String} [options.profileDir=~/Library/MobileDevice/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {String} [options.profileDir=~/Library/Developer/Xcode/UserData/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {Boolean} [options.unmanaged] - When true, excludes managed provisioning profiles.
* @param {Boolean} [options.validOnly=true] - When true, only returns non-expired, valid provisioning profiles.
* @param {Boolean} [options.watch=false] - If true, watches the specified provisioning profile directory for updates.
Expand All @@ -63,10 +65,10 @@ function detect(options, callback) {
return magik(options, callback, function (emitter, options, callback) {
var files = {},
validOnly = options.validOnly === undefined || options.validOnly === true,
profileDir = appc.fs.resolvePath(options.profileDir || defaultProfileDir),
profileDirs = getExistingProvisioningProfileDirectories(options.profileDir),
results = {
provisioning: {
profileDir: profileDir,
profileDir: profileDirs[0],
development: [],
adhoc: [],
enterprise: [],
Expand All @@ -82,51 +84,53 @@ function detect(options, callback) {
},

ppRegExp = /.*\.(mobileprovision|provisionprofile)$/;


if (options.watch) {
var throttleTimer = null;

if (!watchers[profileDir]) {
watchers[profileDir] = {
handle: fs.watch(profileDir, { persistent: false }, function (event, filename) {
if (!ppRegExp.test(filename)) {
// if it's not a provisioning profile, we don't care about it
return;
}

var file = path.join(profileDir, filename);

if (event === 'rename') {
if (files[file]) {
if (fs.existsSync(file)) {
// change, reload the provisioning profile
parseProfile(file);
for (const profileDir of profileDirs) {
if (!watchers[profileDir]) {
watchers[profileDir] = {
handle: fs.watch(profileDir, { persistent: false }, function (event, filename) {
if (!ppRegExp.test(filename)) {
// if it's not a provisioning profile, we don't care about it
return;
}

var file = path.join(profileDir, filename);

if (event === 'rename') {
if (files[file]) {
if (fs.existsSync(file)) {
// change, reload the provisioning profile
parseProfile(file);
} else {
// delete
removeProfile(file);
}
} else {
// delete
removeProfile(file);
// add
parseProfile(file);
}
} else {
// add
} else if (event === 'change') {
// updated
parseProfile(file);
}
} else if (event === 'change') {
// updated
parseProfile(file);
}

clearTimeout(throttleTimer);

throttleTimer = setTimeout(function () {
detectIssues();
emitter.emit('detected', results);
}, 250);
}),
count: 0
};

clearTimeout(throttleTimer);

throttleTimer = setTimeout(function () {
detectIssues();
emitter.emit('detected', results);
}, 250);
}),
count: 0
};
}

watchers[profileDir].count++;
}

watchers[profileDir].count++;
}

if (cache && !options.bypassCache) {
Expand All @@ -137,7 +141,7 @@ function detect(options, callback) {
function detectIssues() {
results.issues = [];

if (!results.provisioning.development.length || !valid.development) {
if (results.provisioning.development.length > 0 && !valid.development) {
results.issues.push({
id: 'IOS_NO_VALID_DEVELOPMENT_PROVISIONING_PROFILES',
type: 'warning',
Expand All @@ -146,7 +150,7 @@ function detect(options, callback) {
});
}

if (!results.provisioning.adhoc.length || !valid.adhoc) {
if (results.provisioning.adhoc.length > 0 && !valid.adhoc) {
results.issues.push({
id: 'IOS_NO_VALID_ADHOC_PROVISIONING_PROFILES',
type: 'warning',
Expand All @@ -155,7 +159,7 @@ function detect(options, callback) {
});
}

if (!results.provisioning.distribution.length || !valid.distribution) {
if (results.provisioning.distribution.length > 0 && !valid.distribution) {
results.issues.push({
id: 'IOS_NO_VALID_DISTRIBUTION_PROVISIONING_PROFILES',
type: 'warning',
Expand Down Expand Up @@ -245,16 +249,16 @@ function detect(options, callback) {
}
}

fs.exists(profileDir, function (exists) {
exists && fs.readdirSync(profileDir).forEach(function (name) {
for (const profileDir of profileDirs) {
fs.readdirSync(profileDir).forEach(function (name) {
ppRegExp.test(name) && parseProfile(path.join(profileDir, name));
});
}
cb1kenobi marked this conversation as resolved.
Show resolved Hide resolved

detectIssues();
cache = results;
emitter.emit('detected', results);
return callback(null, results);
});
detectIssues();
cache = results;
emitter.emit('detected', results);
return callback(null, results);
});
};

Expand Down Expand Up @@ -332,7 +336,7 @@ function find(options, callback) {
* Watches a provisioning profile directory for file changes.
*
* @param {Object} [options] - An object containing various settings.
* @param {String} [options.profileDir=~/Library/MobileDevice/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {String} [options.profileDir=~/Library/Developer/Xcode/UserData/Provisioning Profiles] - The path to search for provisioning profiles.
* @param {Function} [callback(err, results)] - A function to call with the provisioning profile information.
*
* @returns {Function} A function that unwatches changes.
Expand All @@ -358,19 +362,46 @@ function watch(options, callback) {
/**
* Stops watching the specified provisioning profile directory.
*
* @param {String} [profileDir=~/Library/MobileDevice/Provisioning Profiles] - The path to the provisioning profile directory.
* @param {String} [profileDir=~/Library/Developer/Xcode/UserData/Provisioning Profiles] - The path to the provisioning profile directory.
*/
function unwatch(profileDir) {
var profileDir = appc.fs.resolvePath(profileDir || defaultProfileDir);
var profileDirs = getExistingProvisioningProfileDirectories(profileDir);

if (!watchers[profileDir]) return;
for (const profileDir of profileDirs) {
if (!watchers[profileDir]) continue;

if (--watchers[profileDir].count <= 0) {
watchers[profileDir].handle.close();
delete watchers[profileDir];
if (--watchers[profileDir].count <= 0) {
watchers[profileDir].handle.close();
delete watchers[profileDir];
}
}
};

/**
* Searches for existing provisioning profile directories.
*
* @throws
* @param {string | undefined} profileDir A custom directory set by the developer.
* @returns {string[]} The directories that exist on the filesystem.
*/
function getExistingProvisioningProfileDirectories(profileDir) {
const profileDirectories = [];

for (const directory of [profileDir, ...provisioningProfilesDirectories]) {
if (!directory) {
continue;
}

const resolvedDirectory = appc.fs.resolvePath(directory);

if (fs.existsSync(resolvedDirectory)) {
profileDirectories.push(resolvedDirectory);
}
}

return profileDirectories;
}

/*
* If the app exits, close all filesystem watchers.
*/
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ioslib",
"version": "1.7.38",
"version": "1.7.39",
"description": "iOS Utility Library",
"keywords": [
"appcelerator",
Expand Down
Loading