Skip to content

Commit

Permalink
Merge pull request #244 from tidev/fix/new-provisioning-profile-direc…
Browse files Browse the repository at this point in the history
…tory
  • Loading branch information
cb1kenobi authored Sep 30, 2024
2 parents 723a928 + 9f60cf4 commit d485843
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 62 deletions.
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));
});
}

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

0 comments on commit d485843

Please sign in to comment.