diff --git a/index.js b/index.js index 7e31c4b..c66b04c 100644 --- a/index.js +++ b/index.js @@ -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 security 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. diff --git a/lib/provisioning.js b/lib/provisioning.js index 28b09de..41c0011 100644 --- a/lib/provisioning.js +++ b/lib/provisioning.js @@ -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 = {}; @@ -37,7 +40,6 @@ var cache = null, * @type {Error} */ -exports.defaultProfileDir = defaultProfileDir; exports.detect = detect; exports.find = find; exports.watch = watch; @@ -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. @@ -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: [], @@ -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) { @@ -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', @@ -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', @@ -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', @@ -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); }); }; @@ -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. @@ -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. */ diff --git a/package-lock.json b/package-lock.json index d609d99..5388758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ioslib", - "version": "1.7.38", + "version": "1.7.39", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ioslib", - "version": "1.7.38", + "version": "1.7.39", "license": "Apache-2.0", "dependencies": { "always-tail": "0.2.0", diff --git a/package.json b/package.json index ad7f05d..79991cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ioslib", - "version": "1.7.38", + "version": "1.7.39", "description": "iOS Utility Library", "keywords": [ "appcelerator",