appium-xcode 4.0.5 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/helpers.js ADDED
@@ -0,0 +1,72 @@
1
+ import _ from 'lodash';
2
+ import B from 'bluebird';
3
+ import { exec } from 'teen_process';
4
+ import { fs, plist } from '@appium/support';
5
+ import path from 'path';
6
+
7
+ export const XCRUN_TIMEOUT = 15000;
8
+
9
+ /**
10
+ * Executes 'xcrun' command line utility
11
+ *
12
+ * @param {string[]} args xcrun arguments
13
+ * @param {number} timeout [15000] The maximum number of milliseconds to wait until xcrun exists
14
+ * @returns {Promise<import("teen_process").ExecResult>} The result of xcrun execution
15
+ * @throws {Error} If xcrun returned non-zero exit code or timed out
16
+ */
17
+ export async function runXcrunCommand (args, timeout = XCRUN_TIMEOUT) {
18
+ try {
19
+ return await exec('xcrun', args, {timeout});
20
+ } catch (err) {
21
+ // the true error can be hidden within the stderr
22
+ if (err.stderr) {
23
+ err.message = `${err.message}: ${err.stderr}`;
24
+ }
25
+
26
+ throw err;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Uses macOS Spotlight service to detect where the given app is installed
32
+ *
33
+ * @param {string} bundleId Bundle identifier of the target app
34
+ * @returns {Promise<string[]>} Full paths to where the app with the given bundle id is present.
35
+ */
36
+ export async function findAppPaths (bundleId) {
37
+ let stdout;
38
+ try {
39
+ ({stdout} = await exec('/usr/bin/mdfind', [
40
+ `kMDItemCFBundleIdentifier=${bundleId}`
41
+ ]));
42
+ } catch (e) {
43
+ return [];
44
+ }
45
+
46
+ const matchedPaths = _.trim(stdout)
47
+ .split('\n')
48
+ .map(_.trim)
49
+ .filter(Boolean);
50
+ if (_.isEmpty(matchedPaths)) {
51
+ return [];
52
+ }
53
+ const results = matchedPaths.map((p) => (async () => {
54
+ if (await fs.exists(p)) {
55
+ return p;
56
+ }
57
+ })());
58
+ return (await B.all(results)).filter(Boolean);
59
+ }
60
+
61
+ /**
62
+ * Finds and retrieves the content of the Xcode's Info.plist file
63
+ *
64
+ * @param {string} developerRoot Full path to the Contents/Developer folder under Xcode.app root
65
+ * @returns {Promise<object>} All plist entries as an object or an empty object if no plist was found
66
+ */
67
+ export async function readXcodePlist (developerRoot) {
68
+ const plistPath = path.resolve(developerRoot, '..', 'Info.plist');
69
+ return await fs.exists(plistPath)
70
+ ? await plist.parsePlistFile(plistPath)
71
+ : {};
72
+ }
package/lib/xcode.js CHANGED
@@ -1,141 +1,133 @@
1
- import { util, fs, plist, logger } from '@appium/support';
1
+ import { fs, logger } from '@appium/support';
2
2
  import path from 'path';
3
3
  import { retry } from 'asyncbox';
4
4
  import _ from 'lodash';
5
- import { parse as parsePlistData } from 'plist';
6
5
  import { exec } from 'teen_process';
7
6
  import semver from 'semver';
7
+ import {
8
+ runXcrunCommand, findAppPaths, XCRUN_TIMEOUT, readXcodePlist
9
+ } from './helpers';
8
10
 
9
-
10
- const env = process.env;
11
-
12
- const XCRUN_TIMEOUT = 15000;
13
- const XCODE_SUBDIR = '/Contents/Developer';
14
- const DEFAULT_NUMBER_OF_RETRIES = 3;
11
+ const DEFAULT_NUMBER_OF_RETRIES = 2;
12
+ const XCODE_BUNDLE_ID = 'com.apple.dt.Xcode';
15
13
 
16
14
  const log = logger.getLogger('Xcode');
17
15
 
16
+ /**
17
+ * Retrieves the full path to Xcode Developer subfolder via xcode-select
18
+ *
19
+ * @param {number} timeout The maximum timeout for xcode-select execution
20
+ * @returns {Promise<string>} Full path to Xcode Developer subfolder
21
+ * @throws {Error} If it is not possible to retrieve a proper path
22
+ */
23
+ async function getPathFromXcodeSelect (timeout = XCRUN_TIMEOUT) {
24
+ const generateErrorMessage = async (prefix) => {
25
+ const xcodePaths = await findAppPaths(XCODE_BUNDLE_ID);
26
+ if (_.isEmpty(xcodePaths)) {
27
+ return `${prefix}. Consider installing Xcode to address this issue.`;
28
+ }
18
29
 
19
- function hasExpectedSubDir (path) {
20
- return path.substring(path.length - XCODE_SUBDIR.length) === XCODE_SUBDIR;
21
- }
30
+ const proposals = xcodePaths.map((p) => ` sudo xcode-select -s "${path.join(p, 'Contents', 'Developer')}"`);
31
+ return `${prefix}. ` +
32
+ `Consider running${proposals.length > 1 ? ' any of' : ''}:\n${'\n'.join(proposals)}\nto address this issue.`;
33
+ };
22
34
 
23
- async function runXcrunCommand (args, timeout = XCRUN_TIMEOUT) {
35
+ let stdout;
24
36
  try {
25
- const res = await exec('xcrun', args, {timeout});
26
- if (_.isUndefined(res)) {
27
- throw new Error(`Nothing returned from trying to run 'xcrun ${args.join(' ')}'`);
28
- }
29
- return res;
30
- } catch (err) {
31
- // the true error can be hidden within the stderr
32
- if (err.stderr) {
33
- err.message = `${err.message}: ${err.stderr}`;
34
- }
35
-
36
- throw err;
37
+ ({stdout} = await exec('xcode-select', ['--print-path'], {timeout}));
38
+ } catch (e) {
39
+ log.errorAndThrow(`Cannot determine the path to Xcode by running 'xcode-select -p' command. ` +
40
+ `Original error: ${e.stderr || e.message}`);
37
41
  }
38
- }
39
-
40
- async function getPathFromSymlink (failMessage) {
41
- // Node's invocation of xcode-select sometimes flakes and returns an empty string.
42
- // Not clear why. As a workaround, Appium can reliably deduce the version in use by checking
43
- // the locations xcode-select uses to store the selected version's path. This should be 100%
44
- // reliable so long as the link locations remain the same. However, since we're relying on
45
- // hardcoded paths, this approach will break the next time Apple changes the symlink location.
46
- log.warn(`Finding XcodePath by symlink because ${failMessage}`);
47
-
48
- const symlinkPath = '/var/db/xcode_select_link';
49
- const legacySymlinkPath = '/usr/share/xcode-select/xcode_dir_link'; // Xcode < 5.x
50
- let xcodePath = null;
51
-
52
- // xcode-select allows users to override its settings with the DEVELOPER_DIR env var,
53
- // so check that first
54
- if (util.hasContent(env.DEVELOPER_DIR)) {
55
- const customPath = hasExpectedSubDir(env.DEVELOPER_DIR)
56
- ? env.DEVELOPER_DIR
57
- : env.DEVELOPER_DIR + XCODE_SUBDIR;
58
-
59
- if (await fs.exists(customPath)) {
60
- xcodePath = customPath;
61
- } else {
62
- let mesg = `Could not find path to Xcode, environment variable ` +
63
- `DEVELOPER_DIR set to: ${env.DEVELOPER_DIR} ` +
64
- `but no Xcode found`;
65
- log.warn(mesg);
66
- throw new Error(mesg);
67
- }
68
- } else if (await fs.exists(symlinkPath)) {
69
- xcodePath = await fs.readlink(symlinkPath);
70
- } else if (await fs.exists(legacySymlinkPath)) {
71
- xcodePath = await fs.readlink(legacySymlinkPath);
42
+ // trim and remove trailing slash
43
+ const developerRoot = stdout.replace(/\/$/, '').trim();
44
+ if (!developerRoot) {
45
+ log.errorAndThrow(await generateErrorMessage(`'xcode-select -p' returned an empty string`));
72
46
  }
73
-
74
- if (xcodePath) {
75
- return xcodePath.replace(new RegExp('/$'), '').trim();
47
+ // xcode-select might also return a path to command line tools
48
+ const {CFBundleIdentifier} = await readXcodePlist(developerRoot);
49
+ if (CFBundleIdentifier === XCODE_BUNDLE_ID) {
50
+ return developerRoot;
76
51
  }
77
52
 
78
- // We should only get here is we failed to capture xcode-select's stdout and our
79
- // other checks failed. Either Apple has moved the symlink to a new location or the user
80
- // is not using the default install. 99.999% chance it's the latter, so issue a warning
81
- // should we ever hit the edge case.
82
- let msg = `Could not find path to Xcode by symlinks located in ${symlinkPath}, or ${legacySymlinkPath}`;
83
- log.warn(msg);
84
- throw new Error(msg);
53
+ log.errorAndThrow(await generateErrorMessage(`'${developerRoot}' is not a valid Xcode path`));
85
54
  }
86
55
 
87
- async function getPathFromXcodeSelect (timeout = XCRUN_TIMEOUT) {
88
- let {stdout} = await exec('xcode-select', ['--print-path'], {timeout});
89
-
90
- // trim and remove trailing slash
91
- const xcodeFolderPath = stdout.replace(/\/$/, '').trim();
92
-
93
- if (!util.hasContent(xcodeFolderPath)) {
94
- log.errorAndThrow('xcode-select returned an empty string');
56
+ /**
57
+ * Retrieves the full path to Xcode Developer subfolder via DEVELOPER_DIR environment variable
58
+ *
59
+ * @returns {Promise<string>} Full path to Xcode Developer subfolder
60
+ * @throws {Error} If it is not possible to retrieve a proper path
61
+ */
62
+ async function getPathFromDeveloperDir () {
63
+ const developerRoot = process.env.DEVELOPER_DIR;
64
+ const {CFBundleIdentifier} = await readXcodePlist(developerRoot);
65
+ if (CFBundleIdentifier === XCODE_BUNDLE_ID) {
66
+ return developerRoot;
95
67
  }
96
68
 
97
- if (await fs.exists(xcodeFolderPath)) {
98
- return xcodeFolderPath;
99
- } else {
100
- const msg = `xcode-select could not find xcode. Path '${xcodeFolderPath}' does not exist.`;
101
- log.errorAndThrow(msg);
102
- }
69
+ log.errorAndThrow(`The path to Xcode Developer dir '${developerRoot}' provided in DEVELOPER_DIR ` +
70
+ `environment variable is not a valid path`);
103
71
  }
104
72
 
73
+ /**
74
+ * Retrieves the full path to Xcode Developer subfolder.
75
+ * If DEVELOPER_DIR environment variable is provided then its value has a priority.
76
+ *
77
+ * @property {number} timeout [15000] The maximum timeout for xcode-select execution
78
+ * @returns {string} Full path to Xcode Developer subfolder
79
+ * @throws {Error} If there was an error while retrieving the path.
80
+ */
105
81
  const getPath = _.memoize(function getPath (timeout = XCRUN_TIMEOUT) {
106
- // first we try using xcode-select to find the path
107
- // then we try using the symlinks that Apple has by default
108
- return (async () => {
109
- try {
110
- return await getPathFromXcodeSelect(timeout);
111
- } catch (e) {
112
- return await getPathFromSymlink(e.message);
113
- }
114
- })();
82
+ return process.env.DEVELOPER_DIR ? getPathFromDeveloperDir() : getPathFromXcodeSelect(timeout);
115
83
  });
116
84
 
117
-
85
+ /**
86
+ * Retrieves Xcode version
87
+ *
88
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands.
89
+ * @returns {Promise<import("semver").SemVer | null>} Xcode version
90
+ * @throws {Error} If there was a failure while retrieving the version
91
+ */
118
92
  async function getVersionWithoutRetry (timeout = XCRUN_TIMEOUT) {
119
- const xcodePath = await getPath(timeout);
120
-
93
+ const developerPath = await getPath(timeout);
121
94
  // we want to read the CFBundleShortVersionString from Xcode's plist.
122
- // It should be in /[root]/XCode.app/Contents/
123
- const plistPath = path.resolve(xcodePath, '..', 'Info.plist');
124
-
125
- if (!await fs.exists(plistPath)) {
126
- throw new Error(`Could not get Xcode version. ${plistPath} does not exist on disk.`);
127
- }
128
-
129
- const version = await plist.parsePlistFile(plistPath);
130
- return semver.coerce(version.CFBundleShortVersionString);
95
+ const {CFBundleShortVersionString} = await readXcodePlist(developerPath);
96
+ return semver.coerce(CFBundleShortVersionString);
131
97
  }
132
98
 
99
+ /**
100
+ * Retrieves Xcode version or the cached one if called more than once
101
+ *
102
+ * @param {number} retries [2] How many retries to apply for version retrieval
103
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
104
+ * @returns {Promise<import("semver").SemVer | null>} Xcode version
105
+ * @throws {Error} If there was a failure while retrieving the version
106
+ */
133
107
  const getVersionMemoized = _.memoize(
134
108
  function getVersionMemoized (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
135
109
  return retry(retries, getVersionWithoutRetry, timeout);
136
110
  }
137
111
  );
138
112
 
113
+ /**
114
+ * @typedef {Object} XcodeVersion
115
+ * @property {string} versionString Xcode version as a string
116
+ * @property {number} versionFloat Xcode version as a float number
117
+ * @property {number} major Major number of Xcode version
118
+ * @property {number} minor Minor number of Xcode version
119
+ * @property {number?} patch Patch number of Xcode version (if exists)
120
+ */
121
+
122
+ /**
123
+ * Retrieves Xcode version
124
+ *
125
+ * @param {boolean} parse [false] Whether to parse the version to a XcodeVersion version
126
+ * @param {number} retries [2] How many retries to apply for getting the version number
127
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
128
+ * @returns {Promise<XcodeVersion | string>} Xcode version depending on the value of `parse` flag
129
+ * @throws {Error} If there was a failure while retrieving the version
130
+ */
139
131
  async function getVersion (parse = false, retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
140
132
  const version = await getVersionMemoized(retries, timeout);
141
133
  // xcode version strings are not exactly semver string: patch versions of 0
@@ -157,37 +149,11 @@ async function getVersion (parse = false, retries = DEFAULT_NUMBER_OF_RETRIES, t
157
149
  };
158
150
  }
159
151
 
160
- async function getCommandLineToolsVersion () {
161
- // there are a number of different ways that the CLI tools version has been
162
- // represented. Try them from most reliable to least, falling down the chain
163
- const getVersionFunctions = [
164
- async () => {
165
- let pkg = (await exec('pkgutil', ['--pkgs=com.apple.pkg.DevSDK_.*'])).stdout;
166
- return (await exec('pkgutil', [`--pkg-info=${pkg.trim()}`])).stdout;
167
- },
168
- async () => (await exec('pkgutil', [`--pkg-info=com.apple.pkg.CLTools_Executables`])).stdout,
169
- async () => (await exec('pkgutil', [`--pkg-info=com.apple.pkg.DeveloperToolsCLI`])).stdout,
170
- ];
171
- let stdout;
172
- for (let getVersion of getVersionFunctions) {
173
- try {
174
- stdout = await getVersion();
175
- break;
176
- } catch (ign) {
177
- stdout = '';
178
- }
179
- }
180
-
181
- // stdout should have a line like `version: 8.0.0.0.1.1472435881`
182
- let match = /^version: (.+)$/m.exec(stdout); // https://regex101.com/r/HV3x4d/1
183
- return match ? match[1] : undefined;
184
- }
185
-
186
152
  /**
187
153
  * Check https://trac.macports.org/wiki/XcodeVersionInfo
188
154
  * to see the actual mapping between clang and other components.
189
155
  *
190
- * @returns {?string} The actual Clang version in x.x.x.x or x.x.x format,
156
+ * @returns {Promise<string?>} The actual Clang version in x.x.x.x or x.x.x format,
191
157
  * which is supplied with Command Line Tools. `null` is returned
192
158
  * if CLT are not installed.
193
159
  */
@@ -208,170 +174,71 @@ async function getClangVersion () {
208
174
  return match[1];
209
175
  }
210
176
 
211
- async function getAutomationTraceTemplatePathWithoutRetry (timeout = XCRUN_TIMEOUT) {
212
- const xcodePath = await getPath(timeout);
213
-
214
- // for ios 8 and up, the file extension for AutiomationInstrument changed.
215
- // rather than waste time getting the iOSSDKVersion, just get both paths and see which one exists
216
- const extensions = ['xrplugin', 'bundle'];
217
- const pathPrefix = path.resolve(xcodePath, '../Applications/Instruments.app/Contents/PlugIns');
218
- const pathSuffix = 'Contents/Resources/Automation.tracetemplate';
219
- let automationTraceTemplatePaths = [
220
- path.resolve(pathPrefix, `AutomationInstrument.${extensions[0]}`, pathSuffix),
221
- path.resolve(pathPrefix, `AutomationInstrument.${extensions[1]}`, pathSuffix)
222
- ];
223
-
224
- if (await fs.exists(automationTraceTemplatePaths[0])) {
225
- return automationTraceTemplatePaths[0];
226
- }
227
-
228
- if (await fs.exists(automationTraceTemplatePaths[1])) {
229
- return automationTraceTemplatePaths[1];
230
- }
231
-
232
- const msg = 'Could not find Automation.tracetemplate in any of the following' +
233
- `locations ${automationTraceTemplatePaths.toString()}`;
234
- log.error(msg);
235
- throw new Error(msg);
236
-
237
- }
238
-
239
- const getAutomationTraceTemplatePath = _.memoize(
240
- function getAutomationTraceTemplatePath (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
241
- return retry(retries, getAutomationTraceTemplatePathWithoutRetry, timeout);
242
- }
243
- );
244
-
177
+ /**
178
+ * Retrieves the maximum version of iOS SDK supported by the installed Xcode
179
+ *
180
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
181
+ * @returns {string} The SDK version
182
+ * @throws {Error} If the SDK version number cannot be determined
183
+ */
245
184
  async function getMaxIOSSDKWithoutRetry (timeout = XCRUN_TIMEOUT) {
246
- const version = await getVersion(false, DEFAULT_NUMBER_OF_RETRIES, timeout);
247
- if (version[0] === '4') {
248
- return '6.1';
249
- }
250
-
251
185
  const args = ['--sdk', 'iphonesimulator', '--show-sdk-version'];
252
186
  const {stdout} = await runXcrunCommand(args, timeout);
253
-
254
187
  const sdkVersion = stdout.trim();
255
188
  const match = /\d.\d/.exec(stdout);
256
-
257
189
  if (!match) {
258
190
  throw new Error(`xcrun returned a non-numeric iOS SDK version: '${sdkVersion}'`);
259
191
  }
260
-
261
192
  return sdkVersion;
262
193
  }
263
194
 
264
- async function getMaxIOSSDKFromXcodeVersion (timeout = XCRUN_TIMEOUT) {
265
- const version = await getVersion(true, DEFAULT_NUMBER_OF_RETRIES, timeout);
266
- // as of now, the iOS version associated with an Xcode version is
267
- // just the Xcode version + 2
268
- return `${version.major + 2}.${version.minor}`;
269
- }
270
-
195
+ /**
196
+ * Retrieves the maximum version of iOS SDK supported by the installed Xcode
197
+ *
198
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
199
+ * @param {number} retries [2] The maximum number of retries
200
+ * @returns {string} The SDK version
201
+ * @throws {Error} If the SDK version number cannot be determined
202
+ */
271
203
  const getMaxIOSSDK = _.memoize(
272
204
  function getMaxIOSSDK (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
273
- try {
274
- return retry(retries, getMaxIOSSDKWithoutRetry, timeout);
275
- } catch (err) {
276
- log.warn(`Unable to retrieve maximum iOS version: ${err.message}`);
277
- log.warn('Guessing from Xcode version');
278
- return getMaxIOSSDKFromXcodeVersion(timeout);
279
- }
205
+ return retry(retries, getMaxIOSSDKWithoutRetry, timeout);
280
206
  }
281
207
  );
282
208
 
209
+ /**
210
+ * Retrieves the maximum version of tvOS SDK supported by the installed Xcode
211
+ *
212
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
213
+ * @returns {string} The SDK version
214
+ * @throws {Error} If the SDK version number cannot be determined
215
+ */
283
216
  async function getMaxTVOSSDKWithoutRetry (timeout = XCRUN_TIMEOUT) {
284
217
  const args = ['--sdk', 'appletvsimulator', '--show-sdk-version'];
285
218
  const {stdout} = await runXcrunCommand(args, timeout);
286
-
287
219
  const sdkVersion = stdout.trim();
288
-
289
220
  if (isNaN(parseFloat(sdkVersion))) {
290
221
  throw new Error(`xcrun returned a non-numeric tvOS SDK version: '${sdkVersion}'`);
291
222
  }
292
-
293
223
  return sdkVersion;
294
224
  }
295
225
 
226
+ /**
227
+ * Retrieves the maximum version of tvOS SDK supported by the installed Xcode
228
+ *
229
+ * @param {number} timeout [15000] Timeout of milliseconds to wait for terminal commands
230
+ * @param {number} retries [2] The maximum number of retries
231
+ * @returns {string} The SDK version
232
+ * @throws {Error} If the SDK version number cannot be determined
233
+ */
296
234
  const getMaxTVOSSDK = _.memoize(
297
235
  function getMaxTVOSSDK (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
298
236
  return retry(retries, getMaxTVOSSDKWithoutRetry, timeout);
299
237
  }
300
238
  );
301
239
 
302
- async function getConnectedDevices (timeout = XCRUN_TIMEOUT) {
303
- const cmd = '/usr/sbin/system_profiler';
304
- const args = ['-xml', 'SPUSBDataType'];
305
- let {stdout} = await exec(cmd, args, {timeout});
306
- let plistContent = parsePlistData(stdout);
307
-
308
- let devicesFound = [];
309
- let entriesToSearch = [plistContent[0]];
310
- while (entriesToSearch.length > 0) {
311
- let currentEntry = entriesToSearch.pop();
312
- if (currentEntry instanceof Array) {
313
- entriesToSearch = entriesToSearch.concat(currentEntry);
314
- } else if ((currentEntry._name &&
315
- currentEntry._name.substring(0, 4) === 'iPad') ||
316
- (currentEntry._name &&
317
- currentEntry._name.substring(0, 6) === 'iPhone') ||
318
- (currentEntry._name && _.includes(currentEntry._name, 'Apple TV'))) {
319
- let deviceInfo = {
320
- name: currentEntry._name,
321
- udid: currentEntry.serial_num,
322
- productId: currentEntry.product_id,
323
- deviceVersion: currentEntry.bcd_device
324
- };
325
- devicesFound.push(deviceInfo);
326
- } else if (currentEntry._items) {
327
- entriesToSearch = entriesToSearch.concat(currentEntry._items);
328
- }
329
- }
330
- return devicesFound;
331
- }
332
-
333
- async function getInstrumentsPathWithoutRetry (timeout = XCRUN_TIMEOUT) {
334
- const args = ['-find', 'instruments'];
335
- let {stdout} = await runXcrunCommand(args, timeout);
336
-
337
- if (!stdout) {
338
- stdout = '';
339
- }
340
-
341
- let instrumentsPath = stdout.trim();
342
-
343
- if (!instrumentsPath) {
344
- throw new Error(`Could not find path to instruments binary using 'xcrun ${args.join(' ')}'`);
345
- }
346
-
347
- return instrumentsPath;
348
- }
349
-
350
- const getInstrumentsPath = _.memoize(
351
- function getInstrumentsPath (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {
352
- return retry(retries, getInstrumentsPathWithoutRetry, timeout);
353
- }
354
- );
355
-
356
- function clearInternalCache () {
357
-
358
- // memoized functions
359
- const memoized = [
360
- getPath, getVersionMemoized, getAutomationTraceTemplatePath, getMaxIOSSDK,
361
- getMaxTVOSSDK, getInstrumentsPath,
362
- ];
363
-
364
- memoized.forEach((f) => {
365
- if (f.cache) {
366
- f.cache = new _.memoize.Cache();
367
- }
368
- });
369
- }
370
-
371
240
  export {
372
- getPath, getVersion, getAutomationTraceTemplatePath, getMaxIOSSDK,
373
- getAutomationTraceTemplatePathWithoutRetry, getMaxIOSSDKWithoutRetry,
374
- getConnectedDevices, clearInternalCache, getInstrumentsPath,
375
- getCommandLineToolsVersion, getMaxTVOSSDK, getMaxTVOSSDKWithoutRetry,
376
- getClangVersion,
241
+ getPath, getVersion, getMaxIOSSDK, getMaxIOSSDKWithoutRetry,
242
+ getMaxTVOSSDK, getMaxTVOSSDKWithoutRetry, getClangVersion,
243
+ getPathFromDeveloperDir, getPathFromXcodeSelect,
377
244
  };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "ios",
7
7
  "xcode"
8
8
  ],
9
- "version": "4.0.5",
9
+ "version": "5.0.1",
10
10
  "author": "Appium Contributors",
11
11
  "license": "Apache-2.0",
12
12
  "repository": {
@@ -90,6 +90,6 @@
90
90
  "mocha": "^10.0.0",
91
91
  "pre-commit": "^1.1.3",
92
92
  "prettier": "^2.7.1",
93
- "semantic-release": "^19.0.2"
93
+ "semantic-release": "^20.0.2"
94
94
  }
95
95
  }