appium-xcode 4.0.4 → 5.0.0
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/CHANGELOG.md +7 -0
- package/README.md +7 -29
- package/build/index.js +43 -33
- package/build/lib/helpers.js +72 -0
- package/build/lib/xcode.js +104 -197
- package/index.js +19 -15
- package/lib/helpers.js +72 -0
- package/lib/xcode.js +130 -263
- package/package.json +2 -2
- package/build/lib/xcode.js.map +0 -1
package/lib/xcode.js
CHANGED
|
@@ -1,141 +1,133 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
35
|
+
let stdout;
|
|
24
36
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
|
|
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
|
|
120
|
-
|
|
93
|
+
const developerPath = await getPath(timeout);
|
|
121
94
|
// we want to read the CFBundleShortVersionString from Xcode's plist.
|
|
122
|
-
|
|
123
|
-
|
|
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 {
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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,
|
|
373
|
-
|
|
374
|
-
|
|
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": "
|
|
9
|
+
"version": "5.0.0",
|
|
10
10
|
"author": "Appium Contributors",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"repository": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"CHANGELOG.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@appium/support": "^
|
|
36
|
+
"@appium/support": "^3.0.0",
|
|
37
37
|
"@babel/runtime": "^7.0.0",
|
|
38
38
|
"asyncbox": "^2.3.0",
|
|
39
39
|
"lodash": "^4.17.4",
|
package/build/lib/xcode.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"xcode.js","names":["env","process","XCRUN_TIMEOUT","XCODE_SUBDIR","DEFAULT_NUMBER_OF_RETRIES","log","logger","getLogger","hasExpectedSubDir","path","substring","length","runXcrunCommand","args","timeout","res","exec","_","isUndefined","Error","join","err","stderr","message","getPathFromSymlink","failMessage","warn","symlinkPath","legacySymlinkPath","xcodePath","util","hasContent","DEVELOPER_DIR","customPath","fs","exists","mesg","readlink","replace","RegExp","trim","msg","getPathFromXcodeSelect","stdout","xcodeFolderPath","errorAndThrow","getPath","memoize","e","getVersionWithoutRetry","plistPath","resolve","version","plist","parsePlistFile","semver","coerce","CFBundleShortVersionString","getVersionMemoized","retries","retry","getVersion","parse","versionString","patch","major","minor","versionFloat","parseFloat","undefined","toString","getCommandLineToolsVersion","getVersionFunctions","pkg","ign","match","getClangVersion","which","info","getAutomationTraceTemplatePathWithoutRetry","extensions","pathPrefix","pathSuffix","automationTraceTemplatePaths","error","getAutomationTraceTemplatePath","getMaxIOSSDKWithoutRetry","sdkVersion","getMaxIOSSDKFromXcodeVersion","getMaxIOSSDK","getMaxTVOSSDKWithoutRetry","isNaN","getMaxTVOSSDK","getConnectedDevices","cmd","plistContent","parsePlistData","devicesFound","entriesToSearch","currentEntry","pop","Array","concat","_name","includes","deviceInfo","name","udid","serial_num","productId","product_id","deviceVersion","bcd_device","push","_items","getInstrumentsPathWithoutRetry","instrumentsPath","getInstrumentsPath","clearInternalCache","memoized","forEach","f","cache","Cache"],"sources":["../../lib/xcode.js"],"sourcesContent":["import { util, fs, plist, logger } from '@appium/support';\nimport path from 'path';\nimport { retry } from 'asyncbox';\nimport _ from 'lodash';\nimport { parse as parsePlistData } from 'plist';\nimport { exec } from 'teen_process';\nimport semver from 'semver';\n\n\nconst env = process.env;\n\nconst XCRUN_TIMEOUT = 15000;\nconst XCODE_SUBDIR = '/Contents/Developer';\nconst DEFAULT_NUMBER_OF_RETRIES = 3;\n\nconst log = logger.getLogger('Xcode');\n\n\nfunction hasExpectedSubDir (path) {\n return path.substring(path.length - XCODE_SUBDIR.length) === XCODE_SUBDIR;\n}\n\nasync function runXcrunCommand (args, timeout = XCRUN_TIMEOUT) {\n try {\n const res = await exec('xcrun', args, {timeout});\n if (_.isUndefined(res)) {\n throw new Error(`Nothing returned from trying to run 'xcrun ${args.join(' ')}'`);\n }\n return res;\n } catch (err) {\n // the true error can be hidden within the stderr\n if (err.stderr) {\n err.message = `${err.message}: ${err.stderr}`;\n }\n\n throw err;\n }\n}\n\nasync function getPathFromSymlink (failMessage) {\n // Node's invocation of xcode-select sometimes flakes and returns an empty string.\n // Not clear why. As a workaround, Appium can reliably deduce the version in use by checking\n // the locations xcode-select uses to store the selected version's path. This should be 100%\n // reliable so long as the link locations remain the same. However, since we're relying on\n // hardcoded paths, this approach will break the next time Apple changes the symlink location.\n log.warn(`Finding XcodePath by symlink because ${failMessage}`);\n\n const symlinkPath = '/var/db/xcode_select_link';\n const legacySymlinkPath = '/usr/share/xcode-select/xcode_dir_link'; // Xcode < 5.x\n let xcodePath = null;\n\n // xcode-select allows users to override its settings with the DEVELOPER_DIR env var,\n // so check that first\n if (util.hasContent(env.DEVELOPER_DIR)) {\n const customPath = hasExpectedSubDir(env.DEVELOPER_DIR)\n ? env.DEVELOPER_DIR\n : env.DEVELOPER_DIR + XCODE_SUBDIR;\n\n if (await fs.exists(customPath)) {\n xcodePath = customPath;\n } else {\n let mesg = `Could not find path to Xcode, environment variable ` +\n `DEVELOPER_DIR set to: ${env.DEVELOPER_DIR} ` +\n `but no Xcode found`;\n log.warn(mesg);\n throw new Error(mesg);\n }\n } else if (await fs.exists(symlinkPath)) {\n xcodePath = await fs.readlink(symlinkPath);\n } else if (await fs.exists(legacySymlinkPath)) {\n xcodePath = await fs.readlink(legacySymlinkPath);\n }\n\n if (xcodePath) {\n return xcodePath.replace(new RegExp('/$'), '').trim();\n }\n\n // We should only get here is we failed to capture xcode-select's stdout and our\n // other checks failed. Either Apple has moved the symlink to a new location or the user\n // is not using the default install. 99.999% chance it's the latter, so issue a warning\n // should we ever hit the edge case.\n let msg = `Could not find path to Xcode by symlinks located in ${symlinkPath}, or ${legacySymlinkPath}`;\n log.warn(msg);\n throw new Error(msg);\n}\n\nasync function getPathFromXcodeSelect (timeout = XCRUN_TIMEOUT) {\n let {stdout} = await exec('xcode-select', ['--print-path'], {timeout});\n\n // trim and remove trailing slash\n const xcodeFolderPath = stdout.replace(/\\/$/, '').trim();\n\n if (!util.hasContent(xcodeFolderPath)) {\n log.errorAndThrow('xcode-select returned an empty string');\n }\n\n if (await fs.exists(xcodeFolderPath)) {\n return xcodeFolderPath;\n } else {\n const msg = `xcode-select could not find xcode. Path '${xcodeFolderPath}' does not exist.`;\n log.errorAndThrow(msg);\n }\n}\n\nconst getPath = _.memoize(function getPath (timeout = XCRUN_TIMEOUT) {\n // first we try using xcode-select to find the path\n // then we try using the symlinks that Apple has by default\n return (async () => {\n try {\n return await getPathFromXcodeSelect(timeout);\n } catch (e) {\n return await getPathFromSymlink(e.message);\n }\n })();\n});\n\n\nasync function getVersionWithoutRetry (timeout = XCRUN_TIMEOUT) {\n const xcodePath = await getPath(timeout);\n\n // we want to read the CFBundleShortVersionString from Xcode's plist.\n // It should be in /[root]/XCode.app/Contents/\n const plistPath = path.resolve(xcodePath, '..', 'Info.plist');\n\n if (!await fs.exists(plistPath)) {\n throw new Error(`Could not get Xcode version. ${plistPath} does not exist on disk.`);\n }\n\n const version = await plist.parsePlistFile(plistPath);\n return semver.coerce(version.CFBundleShortVersionString);\n}\n\nconst getVersionMemoized = _.memoize(\n function getVersionMemoized (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n return retry(retries, getVersionWithoutRetry, timeout);\n }\n);\n\nasync function getVersion (parse = false, retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n const version = await getVersionMemoized(retries, timeout);\n // xcode version strings are not exactly semver string: patch versions of 0\n // are removed (e.g., '10.0.0' => '10.0')\n const versionString = version.patch > 0 ? version.version : `${version.major}.${version.minor}`;\n if (!parse) {\n return versionString;\n }\n\n return {\n versionString,\n versionFloat: parseFloat(versionString),\n major: version.major,\n minor: version.minor,\n patch: version.patch > 0 ? version.patch : undefined,\n toString () {\n return versionString;\n },\n };\n}\n\nasync function getCommandLineToolsVersion () {\n // there are a number of different ways that the CLI tools version has been\n // represented. Try them from most reliable to least, falling down the chain\n const getVersionFunctions = [\n async () => {\n let pkg = (await exec('pkgutil', ['--pkgs=com.apple.pkg.DevSDK_.*'])).stdout;\n return (await exec('pkgutil', [`--pkg-info=${pkg.trim()}`])).stdout;\n },\n async () => (await exec('pkgutil', [`--pkg-info=com.apple.pkg.CLTools_Executables`])).stdout,\n async () => (await exec('pkgutil', [`--pkg-info=com.apple.pkg.DeveloperToolsCLI`])).stdout,\n ];\n let stdout;\n for (let getVersion of getVersionFunctions) {\n try {\n stdout = await getVersion();\n break;\n } catch (ign) {\n stdout = '';\n }\n }\n\n // stdout should have a line like `version: 8.0.0.0.1.1472435881`\n let match = /^version: (.+)$/m.exec(stdout); // https://regex101.com/r/HV3x4d/1\n return match ? match[1] : undefined;\n}\n\n/**\n * Check https://trac.macports.org/wiki/XcodeVersionInfo\n * to see the actual mapping between clang and other components.\n *\n * @returns {?string} The actual Clang version in x.x.x.x or x.x.x format,\n * which is supplied with Command Line Tools. `null` is returned\n * if CLT are not installed.\n */\nasync function getClangVersion () {\n try {\n await fs.which('clang');\n } catch (e) {\n log.info('Cannot find clang executable on the local system. ' +\n 'Are Xcode Command Line Tools installed?');\n return null;\n }\n const {stdout} = await exec('clang', ['--version']);\n const match = /clang-([0-9.]+)/.exec(stdout);\n if (!match) {\n log.info(`Cannot parse clang version from ${stdout}`);\n return null;\n }\n return match[1];\n}\n\nasync function getAutomationTraceTemplatePathWithoutRetry (timeout = XCRUN_TIMEOUT) {\n const xcodePath = await getPath(timeout);\n\n // for ios 8 and up, the file extension for AutiomationInstrument changed.\n // rather than waste time getting the iOSSDKVersion, just get both paths and see which one exists\n const extensions = ['xrplugin', 'bundle'];\n const pathPrefix = path.resolve(xcodePath, '../Applications/Instruments.app/Contents/PlugIns');\n const pathSuffix = 'Contents/Resources/Automation.tracetemplate';\n let automationTraceTemplatePaths = [\n path.resolve(pathPrefix, `AutomationInstrument.${extensions[0]}`, pathSuffix),\n path.resolve(pathPrefix, `AutomationInstrument.${extensions[1]}`, pathSuffix)\n ];\n\n if (await fs.exists(automationTraceTemplatePaths[0])) {\n return automationTraceTemplatePaths[0];\n }\n\n if (await fs.exists(automationTraceTemplatePaths[1])) {\n return automationTraceTemplatePaths[1];\n }\n\n const msg = 'Could not find Automation.tracetemplate in any of the following' +\n `locations ${automationTraceTemplatePaths.toString()}`;\n log.error(msg);\n throw new Error(msg);\n\n}\n\nconst getAutomationTraceTemplatePath = _.memoize(\n function getAutomationTraceTemplatePath (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n return retry(retries, getAutomationTraceTemplatePathWithoutRetry, timeout);\n }\n);\n\nasync function getMaxIOSSDKWithoutRetry (timeout = XCRUN_TIMEOUT) {\n const version = await getVersion(false, DEFAULT_NUMBER_OF_RETRIES, timeout);\n if (version[0] === '4') {\n return '6.1';\n }\n\n const args = ['--sdk', 'iphonesimulator', '--show-sdk-version'];\n const {stdout} = await runXcrunCommand(args, timeout);\n\n const sdkVersion = stdout.trim();\n const match = /\\d.\\d/.exec(stdout);\n\n if (!match) {\n throw new Error(`xcrun returned a non-numeric iOS SDK version: '${sdkVersion}'`);\n }\n\n return sdkVersion;\n}\n\nasync function getMaxIOSSDKFromXcodeVersion (timeout = XCRUN_TIMEOUT) {\n const version = await getVersion(true, DEFAULT_NUMBER_OF_RETRIES, timeout);\n // as of now, the iOS version associated with an Xcode version is\n // just the Xcode version + 2\n return `${version.major + 2}.${version.minor}`;\n}\n\nconst getMaxIOSSDK = _.memoize(\n function getMaxIOSSDK (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n try {\n return retry(retries, getMaxIOSSDKWithoutRetry, timeout);\n } catch (err) {\n log.warn(`Unable to retrieve maximum iOS version: ${err.message}`);\n log.warn('Guessing from Xcode version');\n return getMaxIOSSDKFromXcodeVersion(timeout);\n }\n }\n);\n\nasync function getMaxTVOSSDKWithoutRetry (timeout = XCRUN_TIMEOUT) {\n const args = ['--sdk', 'appletvsimulator', '--show-sdk-version'];\n const {stdout} = await runXcrunCommand(args, timeout);\n\n const sdkVersion = stdout.trim();\n\n if (isNaN(parseFloat(sdkVersion))) {\n throw new Error(`xcrun returned a non-numeric tvOS SDK version: '${sdkVersion}'`);\n }\n\n return sdkVersion;\n}\n\nconst getMaxTVOSSDK = _.memoize(\n function getMaxTVOSSDK (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n return retry(retries, getMaxTVOSSDKWithoutRetry, timeout);\n }\n);\n\nasync function getConnectedDevices (timeout = XCRUN_TIMEOUT) {\n const cmd = '/usr/sbin/system_profiler';\n const args = ['-xml', 'SPUSBDataType'];\n let {stdout} = await exec(cmd, args, {timeout});\n let plistContent = parsePlistData(stdout);\n\n let devicesFound = [];\n let entriesToSearch = [plistContent[0]];\n while (entriesToSearch.length > 0) {\n let currentEntry = entriesToSearch.pop();\n if (currentEntry instanceof Array) {\n entriesToSearch = entriesToSearch.concat(currentEntry);\n } else if ((currentEntry._name &&\n currentEntry._name.substring(0, 4) === 'iPad') ||\n (currentEntry._name &&\n currentEntry._name.substring(0, 6) === 'iPhone') ||\n (currentEntry._name && _.includes(currentEntry._name, 'Apple TV'))) {\n let deviceInfo = {\n name: currentEntry._name,\n udid: currentEntry.serial_num,\n productId: currentEntry.product_id,\n deviceVersion: currentEntry.bcd_device\n };\n devicesFound.push(deviceInfo);\n } else if (currentEntry._items) {\n entriesToSearch = entriesToSearch.concat(currentEntry._items);\n }\n }\n return devicesFound;\n}\n\nasync function getInstrumentsPathWithoutRetry (timeout = XCRUN_TIMEOUT) {\n const args = ['-find', 'instruments'];\n let {stdout} = await runXcrunCommand(args, timeout);\n\n if (!stdout) {\n stdout = '';\n }\n\n let instrumentsPath = stdout.trim();\n\n if (!instrumentsPath) {\n throw new Error(`Could not find path to instruments binary using 'xcrun ${args.join(' ')}'`);\n }\n\n return instrumentsPath;\n}\n\nconst getInstrumentsPath = _.memoize(\n function getInstrumentsPath (retries = DEFAULT_NUMBER_OF_RETRIES, timeout = XCRUN_TIMEOUT) {\n return retry(retries, getInstrumentsPathWithoutRetry, timeout);\n }\n);\n\nfunction clearInternalCache () {\n\n // memoized functions\n const memoized = [\n getPath, getVersionMemoized, getAutomationTraceTemplatePath, getMaxIOSSDK,\n getMaxTVOSSDK, getInstrumentsPath,\n ];\n\n memoized.forEach((f) => {\n if (f.cache) {\n f.cache = new _.memoize.Cache();\n }\n });\n}\n\nexport {\n getPath, getVersion, getAutomationTraceTemplatePath, getMaxIOSSDK,\n getAutomationTraceTemplatePathWithoutRetry, getMaxIOSSDKWithoutRetry,\n getConnectedDevices, clearInternalCache, getInstrumentsPath,\n getCommandLineToolsVersion, getMaxTVOSSDK, getMaxTVOSSDKWithoutRetry,\n getClangVersion,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA,MAAMA,GAAG,GAAGC,OAAO,CAACD,GAAG;AAEvB,MAAME,aAAa,GAAG,KAAK;AAC3B,MAAMC,YAAY,GAAG,qBAAqB;AAC1C,MAAMC,yBAAyB,GAAG,CAAC;AAEnC,MAAMC,GAAG,GAAGC,eAAM,CAACC,SAAS,CAAC,OAAO,CAAC;AAGrC,SAASC,iBAAiB,CAAEC,IAAI,EAAE;EAChC,OAAOA,IAAI,CAACC,SAAS,CAACD,IAAI,CAACE,MAAM,GAAGR,YAAY,CAACQ,MAAM,CAAC,KAAKR,YAAY;AAC3E;AAEA,eAAeS,eAAe,CAAEC,IAAI,EAAEC,OAAO,GAAGZ,aAAa,EAAE;EAC7D,IAAI;IACF,MAAMa,GAAG,GAAG,MAAM,IAAAC,kBAAI,EAAC,OAAO,EAAEH,IAAI,EAAE;MAACC;IAAO,CAAC,CAAC;IAChD,IAAIG,eAAC,CAACC,WAAW,CAACH,GAAG,CAAC,EAAE;MACtB,MAAM,IAAII,KAAK,CAAE,8CAA6CN,IAAI,CAACO,IAAI,CAAC,GAAG,CAAE,GAAE,CAAC;IAClF;IACA,OAAOL,GAAG;EACZ,CAAC,CAAC,OAAOM,GAAG,EAAE;IAEZ,IAAIA,GAAG,CAACC,MAAM,EAAE;MACdD,GAAG,CAACE,OAAO,GAAI,GAAEF,GAAG,CAACE,OAAQ,KAAIF,GAAG,CAACC,MAAO,EAAC;IAC/C;IAEA,MAAMD,GAAG;EACX;AACF;AAEA,eAAeG,kBAAkB,CAAEC,WAAW,EAAE;EAM9CpB,GAAG,CAACqB,IAAI,CAAE,wCAAuCD,WAAY,EAAC,CAAC;EAE/D,MAAME,WAAW,GAAG,2BAA2B;EAC/C,MAAMC,iBAAiB,GAAG,wCAAwC;EAClE,IAAIC,SAAS,GAAG,IAAI;EAIpB,IAAIC,aAAI,CAACC,UAAU,CAAC/B,GAAG,CAACgC,aAAa,CAAC,EAAE;IACtC,MAAMC,UAAU,GAAGzB,iBAAiB,CAACR,GAAG,CAACgC,aAAa,CAAC,GACnDhC,GAAG,CAACgC,aAAa,GACjBhC,GAAG,CAACgC,aAAa,GAAG7B,YAAY;IAEpC,IAAI,MAAM+B,WAAE,CAACC,MAAM,CAACF,UAAU,CAAC,EAAE;MAC/BJ,SAAS,GAAGI,UAAU;IACxB,CAAC,MAAM;MACL,IAAIG,IAAI,GAAI,qDAAoD,GACpD,yBAAwBpC,GAAG,CAACgC,aAAc,GAAE,GAC5C,oBAAmB;MAC/B3B,GAAG,CAACqB,IAAI,CAACU,IAAI,CAAC;MACd,MAAM,IAAIjB,KAAK,CAACiB,IAAI,CAAC;IACvB;EACF,CAAC,MAAM,IAAI,MAAMF,WAAE,CAACC,MAAM,CAACR,WAAW,CAAC,EAAE;IACvCE,SAAS,GAAG,MAAMK,WAAE,CAACG,QAAQ,CAACV,WAAW,CAAC;EAC5C,CAAC,MAAM,IAAI,MAAMO,WAAE,CAACC,MAAM,CAACP,iBAAiB,CAAC,EAAE;IAC7CC,SAAS,GAAG,MAAMK,WAAE,CAACG,QAAQ,CAACT,iBAAiB,CAAC;EAClD;EAEA,IAAIC,SAAS,EAAE;IACb,OAAOA,SAAS,CAACS,OAAO,CAAC,IAAIC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAACC,IAAI,EAAE;EACvD;EAMA,IAAIC,GAAG,GAAI,uDAAsDd,WAAY,QAAOC,iBAAkB,EAAC;EACvGvB,GAAG,CAACqB,IAAI,CAACe,GAAG,CAAC;EACb,MAAM,IAAItB,KAAK,CAACsB,GAAG,CAAC;AACtB;AAEA,eAAeC,sBAAsB,CAAE5B,OAAO,GAAGZ,aAAa,EAAE;EAC9D,IAAI;IAACyC;EAAM,CAAC,GAAG,MAAM,IAAA3B,kBAAI,EAAC,cAAc,EAAE,CAAC,cAAc,CAAC,EAAE;IAACF;EAAO,CAAC,CAAC;EAGtE,MAAM8B,eAAe,GAAGD,MAAM,CAACL,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAACE,IAAI,EAAE;EAExD,IAAI,CAACV,aAAI,CAACC,UAAU,CAACa,eAAe,CAAC,EAAE;IACrCvC,GAAG,CAACwC,aAAa,CAAC,uCAAuC,CAAC;EAC5D;EAEA,IAAI,MAAMX,WAAE,CAACC,MAAM,CAACS,eAAe,CAAC,EAAE;IACpC,OAAOA,eAAe;EACxB,CAAC,MAAM;IACL,MAAMH,GAAG,GAAI,4CAA2CG,eAAgB,mBAAkB;IAC1FvC,GAAG,CAACwC,aAAa,CAACJ,GAAG,CAAC;EACxB;AACF;AAEA,MAAMK,OAAO,GAAG7B,eAAC,CAAC8B,OAAO,CAAC,SAASD,OAAO,CAAEhC,OAAO,GAAGZ,aAAa,EAAE;EAGnE,OAAO,CAAC,YAAY;IAClB,IAAI;MACF,OAAO,MAAMwC,sBAAsB,CAAC5B,OAAO,CAAC;IAC9C,CAAC,CAAC,OAAOkC,CAAC,EAAE;MACV,OAAO,MAAMxB,kBAAkB,CAACwB,CAAC,CAACzB,OAAO,CAAC;IAC5C;EACF,CAAC,GAAG;AACN,CAAC,CAAC;AAAC;AAGH,eAAe0B,sBAAsB,CAAEnC,OAAO,GAAGZ,aAAa,EAAE;EAC9D,MAAM2B,SAAS,GAAG,MAAMiB,OAAO,CAAChC,OAAO,CAAC;EAIxC,MAAMoC,SAAS,GAAGzC,aAAI,CAAC0C,OAAO,CAACtB,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC;EAE7D,IAAI,EAAC,MAAMK,WAAE,CAACC,MAAM,CAACe,SAAS,CAAC,GAAE;IAC/B,MAAM,IAAI/B,KAAK,CAAE,gCAA+B+B,SAAU,0BAAyB,CAAC;EACtF;EAEA,MAAME,OAAO,GAAG,MAAMC,cAAK,CAACC,cAAc,CAACJ,SAAS,CAAC;EACrD,OAAOK,eAAM,CAACC,MAAM,CAACJ,OAAO,CAACK,0BAA0B,CAAC;AAC1D;AAEA,MAAMC,kBAAkB,GAAGzC,eAAC,CAAC8B,OAAO,CAClC,SAASW,kBAAkB,CAAEC,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACzF,OAAO,IAAA0D,eAAK,EAACD,OAAO,EAAEV,sBAAsB,EAAEnC,OAAO,CAAC;AACxD,CAAC,CACF;AAED,eAAe+C,UAAU,CAAEC,KAAK,GAAG,KAAK,EAAEH,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACtG,MAAMkD,OAAO,GAAG,MAAMM,kBAAkB,CAACC,OAAO,EAAE7C,OAAO,CAAC;EAG1D,MAAMiD,aAAa,GAAGX,OAAO,CAACY,KAAK,GAAG,CAAC,GAAGZ,OAAO,CAACA,OAAO,GAAI,GAAEA,OAAO,CAACa,KAAM,IAAGb,OAAO,CAACc,KAAM,EAAC;EAC/F,IAAI,CAACJ,KAAK,EAAE;IACV,OAAOC,aAAa;EACtB;EAEA,OAAO;IACLA,aAAa;IACbI,YAAY,EAAEC,UAAU,CAACL,aAAa,CAAC;IACvCE,KAAK,EAAEb,OAAO,CAACa,KAAK;IACpBC,KAAK,EAAEd,OAAO,CAACc,KAAK;IACpBF,KAAK,EAAEZ,OAAO,CAACY,KAAK,GAAG,CAAC,GAAGZ,OAAO,CAACY,KAAK,GAAGK,SAAS;IACpDC,QAAQ,GAAI;MACV,OAAOP,aAAa;IACtB;EACF,CAAC;AACH;AAEA,eAAeQ,0BAA0B,GAAI;EAG3C,MAAMC,mBAAmB,GAAG,CAC1B,YAAY;IACV,IAAIC,GAAG,GAAG,CAAC,MAAM,IAAAzD,kBAAI,EAAC,SAAS,EAAE,CAAC,gCAAgC,CAAC,CAAC,EAAE2B,MAAM;IAC5E,OAAO,CAAC,MAAM,IAAA3B,kBAAI,EAAC,SAAS,EAAE,CAAE,cAAayD,GAAG,CAACjC,IAAI,EAAG,EAAC,CAAC,CAAC,EAAEG,MAAM;EACrE,CAAC,EACD,YAAY,CAAC,MAAM,IAAA3B,kBAAI,EAAC,SAAS,EAAE,CAAE,8CAA6C,CAAC,CAAC,EAAE2B,MAAM,EAC5F,YAAY,CAAC,MAAM,IAAA3B,kBAAI,EAAC,SAAS,EAAE,CAAE,4CAA2C,CAAC,CAAC,EAAE2B,MAAM,CAC3F;EACD,IAAIA,MAAM;EACV,KAAK,IAAIkB,UAAU,IAAIW,mBAAmB,EAAE;IAC1C,IAAI;MACF7B,MAAM,GAAG,MAAMkB,UAAU,EAAE;MAC3B;IACF,CAAC,CAAC,OAAOa,GAAG,EAAE;MACZ/B,MAAM,GAAG,EAAE;IACb;EACF;EAGA,IAAIgC,KAAK,GAAG,kBAAkB,CAAC3D,IAAI,CAAC2B,MAAM,CAAC;EAC3C,OAAOgC,KAAK,GAAGA,KAAK,CAAC,CAAC,CAAC,GAAGN,SAAS;AACrC;AAUA,eAAeO,eAAe,GAAI;EAChC,IAAI;IACF,MAAM1C,WAAE,CAAC2C,KAAK,CAAC,OAAO,CAAC;EACzB,CAAC,CAAC,OAAO7B,CAAC,EAAE;IACV3C,GAAG,CAACyE,IAAI,CAAC,oDAAoD,GAC3D,yCAAyC,CAAC;IAC5C,OAAO,IAAI;EACb;EACA,MAAM;IAACnC;EAAM,CAAC,GAAG,MAAM,IAAA3B,kBAAI,EAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;EACnD,MAAM2D,KAAK,GAAG,iBAAiB,CAAC3D,IAAI,CAAC2B,MAAM,CAAC;EAC5C,IAAI,CAACgC,KAAK,EAAE;IACVtE,GAAG,CAACyE,IAAI,CAAE,mCAAkCnC,MAAO,EAAC,CAAC;IACrD,OAAO,IAAI;EACb;EACA,OAAOgC,KAAK,CAAC,CAAC,CAAC;AACjB;AAEA,eAAeI,0CAA0C,CAAEjE,OAAO,GAAGZ,aAAa,EAAE;EAClF,MAAM2B,SAAS,GAAG,MAAMiB,OAAO,CAAChC,OAAO,CAAC;EAIxC,MAAMkE,UAAU,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC;EACzC,MAAMC,UAAU,GAAGxE,aAAI,CAAC0C,OAAO,CAACtB,SAAS,EAAE,kDAAkD,CAAC;EAC9F,MAAMqD,UAAU,GAAG,6CAA6C;EAChE,IAAIC,4BAA4B,GAAG,CACjC1E,aAAI,CAAC0C,OAAO,CAAC8B,UAAU,EAAG,wBAAuBD,UAAU,CAAC,CAAC,CAAE,EAAC,EAAEE,UAAU,CAAC,EAC7EzE,aAAI,CAAC0C,OAAO,CAAC8B,UAAU,EAAG,wBAAuBD,UAAU,CAAC,CAAC,CAAE,EAAC,EAAEE,UAAU,CAAC,CAC9E;EAED,IAAI,MAAMhD,WAAE,CAACC,MAAM,CAACgD,4BAA4B,CAAC,CAAC,CAAC,CAAC,EAAE;IACpD,OAAOA,4BAA4B,CAAC,CAAC,CAAC;EACxC;EAEA,IAAI,MAAMjD,WAAE,CAACC,MAAM,CAACgD,4BAA4B,CAAC,CAAC,CAAC,CAAC,EAAE;IACpD,OAAOA,4BAA4B,CAAC,CAAC,CAAC;EACxC;EAEA,MAAM1C,GAAG,GAAG,iEAAiE,GAChE,aAAY0C,4BAA4B,CAACb,QAAQ,EAAG,EAAC;EAClEjE,GAAG,CAAC+E,KAAK,CAAC3C,GAAG,CAAC;EACd,MAAM,IAAItB,KAAK,CAACsB,GAAG,CAAC;AAEtB;AAEA,MAAM4C,8BAA8B,GAAGpE,eAAC,CAAC8B,OAAO,CAC9C,SAASsC,8BAA8B,CAAE1B,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACrG,OAAO,IAAA0D,eAAK,EAACD,OAAO,EAAEoB,0CAA0C,EAAEjE,OAAO,CAAC;AAC5E,CAAC,CACF;AAAC;AAEF,eAAewE,wBAAwB,CAAExE,OAAO,GAAGZ,aAAa,EAAE;EAChE,MAAMkD,OAAO,GAAG,MAAMS,UAAU,CAAC,KAAK,EAAEzD,yBAAyB,EAAEU,OAAO,CAAC;EAC3E,IAAIsC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;IACtB,OAAO,KAAK;EACd;EAEA,MAAMvC,IAAI,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,CAAC;EAC/D,MAAM;IAAC8B;EAAM,CAAC,GAAG,MAAM/B,eAAe,CAACC,IAAI,EAAEC,OAAO,CAAC;EAErD,MAAMyE,UAAU,GAAG5C,MAAM,CAACH,IAAI,EAAE;EAChC,MAAMmC,KAAK,GAAG,OAAO,CAAC3D,IAAI,CAAC2B,MAAM,CAAC;EAElC,IAAI,CAACgC,KAAK,EAAE;IACV,MAAM,IAAIxD,KAAK,CAAE,kDAAiDoE,UAAW,GAAE,CAAC;EAClF;EAEA,OAAOA,UAAU;AACnB;AAEA,eAAeC,4BAA4B,CAAE1E,OAAO,GAAGZ,aAAa,EAAE;EACpE,MAAMkD,OAAO,GAAG,MAAMS,UAAU,CAAC,IAAI,EAAEzD,yBAAyB,EAAEU,OAAO,CAAC;EAG1E,OAAQ,GAAEsC,OAAO,CAACa,KAAK,GAAG,CAAE,IAAGb,OAAO,CAACc,KAAM,EAAC;AAChD;AAEA,MAAMuB,YAAY,GAAGxE,eAAC,CAAC8B,OAAO,CAC5B,SAAS0C,YAAY,CAAE9B,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACnF,IAAI;IACF,OAAO,IAAA0D,eAAK,EAACD,OAAO,EAAE2B,wBAAwB,EAAExE,OAAO,CAAC;EAC1D,CAAC,CAAC,OAAOO,GAAG,EAAE;IACZhB,GAAG,CAACqB,IAAI,CAAE,2CAA0CL,GAAG,CAACE,OAAQ,EAAC,CAAC;IAClElB,GAAG,CAACqB,IAAI,CAAC,6BAA6B,CAAC;IACvC,OAAO8D,4BAA4B,CAAC1E,OAAO,CAAC;EAC9C;AACF,CAAC,CACF;AAAC;AAEF,eAAe4E,yBAAyB,CAAE5E,OAAO,GAAGZ,aAAa,EAAE;EACjE,MAAMW,IAAI,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,CAAC;EAChE,MAAM;IAAC8B;EAAM,CAAC,GAAG,MAAM/B,eAAe,CAACC,IAAI,EAAEC,OAAO,CAAC;EAErD,MAAMyE,UAAU,GAAG5C,MAAM,CAACH,IAAI,EAAE;EAEhC,IAAImD,KAAK,CAACvB,UAAU,CAACmB,UAAU,CAAC,CAAC,EAAE;IACjC,MAAM,IAAIpE,KAAK,CAAE,mDAAkDoE,UAAW,GAAE,CAAC;EACnF;EAEA,OAAOA,UAAU;AACnB;AAEA,MAAMK,aAAa,GAAG3E,eAAC,CAAC8B,OAAO,CAC7B,SAAS6C,aAAa,CAAEjC,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACpF,OAAO,IAAA0D,eAAK,EAACD,OAAO,EAAE+B,yBAAyB,EAAE5E,OAAO,CAAC;AAC3D,CAAC,CACF;AAAC;AAEF,eAAe+E,mBAAmB,CAAE/E,OAAO,GAAGZ,aAAa,EAAE;EAC3D,MAAM4F,GAAG,GAAG,2BAA2B;EACvC,MAAMjF,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;EACtC,IAAI;IAAC8B;EAAM,CAAC,GAAG,MAAM,IAAA3B,kBAAI,EAAC8E,GAAG,EAAEjF,IAAI,EAAE;IAACC;EAAO,CAAC,CAAC;EAC/C,IAAIiF,YAAY,GAAG,IAAAC,YAAc,EAACrD,MAAM,CAAC;EAEzC,IAAIsD,YAAY,GAAG,EAAE;EACrB,IAAIC,eAAe,GAAG,CAACH,YAAY,CAAC,CAAC,CAAC,CAAC;EACvC,OAAOG,eAAe,CAACvF,MAAM,GAAG,CAAC,EAAE;IACjC,IAAIwF,YAAY,GAAGD,eAAe,CAACE,GAAG,EAAE;IACxC,IAAID,YAAY,YAAYE,KAAK,EAAE;MACjCH,eAAe,GAAGA,eAAe,CAACI,MAAM,CAACH,YAAY,CAAC;IACxD,CAAC,MAAM,IAAKA,YAAY,CAACI,KAAK,IAClBJ,YAAY,CAACI,KAAK,CAAC7F,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,IAC7CyF,YAAY,CAACI,KAAK,IAClBJ,YAAY,CAACI,KAAK,CAAC7F,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAS,IAChDyF,YAAY,CAACI,KAAK,IAAItF,eAAC,CAACuF,QAAQ,CAACL,YAAY,CAACI,KAAK,EAAE,UAAU,CAAE,EAAE;MAC7E,IAAIE,UAAU,GAAG;QACfC,IAAI,EAAEP,YAAY,CAACI,KAAK;QACxBI,IAAI,EAAER,YAAY,CAACS,UAAU;QAC7BC,SAAS,EAAEV,YAAY,CAACW,UAAU;QAClCC,aAAa,EAAEZ,YAAY,CAACa;MAC9B,CAAC;MACDf,YAAY,CAACgB,IAAI,CAACR,UAAU,CAAC;IAC/B,CAAC,MAAM,IAAIN,YAAY,CAACe,MAAM,EAAE;MAC9BhB,eAAe,GAAGA,eAAe,CAACI,MAAM,CAACH,YAAY,CAACe,MAAM,CAAC;IAC/D;EACF;EACA,OAAOjB,YAAY;AACrB;AAEA,eAAekB,8BAA8B,CAAErG,OAAO,GAAGZ,aAAa,EAAE;EACtE,MAAMW,IAAI,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC;EACrC,IAAI;IAAC8B;EAAM,CAAC,GAAG,MAAM/B,eAAe,CAACC,IAAI,EAAEC,OAAO,CAAC;EAEnD,IAAI,CAAC6B,MAAM,EAAE;IACXA,MAAM,GAAG,EAAE;EACb;EAEA,IAAIyE,eAAe,GAAGzE,MAAM,CAACH,IAAI,EAAE;EAEnC,IAAI,CAAC4E,eAAe,EAAE;IACpB,MAAM,IAAIjG,KAAK,CAAE,0DAAyDN,IAAI,CAACO,IAAI,CAAC,GAAG,CAAE,GAAE,CAAC;EAC9F;EAEA,OAAOgG,eAAe;AACxB;AAEA,MAAMC,kBAAkB,GAAGpG,eAAC,CAAC8B,OAAO,CAClC,SAASsE,kBAAkB,CAAE1D,OAAO,GAAGvD,yBAAyB,EAAEU,OAAO,GAAGZ,aAAa,EAAE;EACzF,OAAO,IAAA0D,eAAK,EAACD,OAAO,EAAEwD,8BAA8B,EAAErG,OAAO,CAAC;AAChE,CAAC,CACF;AAAC;AAEF,SAASwG,kBAAkB,GAAI;EAG7B,MAAMC,QAAQ,GAAG,CACfzE,OAAO,EAAEY,kBAAkB,EAAE2B,8BAA8B,EAAEI,YAAY,EACzEG,aAAa,EAAEyB,kBAAkB,CAClC;EAEDE,QAAQ,CAACC,OAAO,CAAEC,CAAC,IAAK;IACtB,IAAIA,CAAC,CAACC,KAAK,EAAE;MACXD,CAAC,CAACC,KAAK,GAAG,IAAIzG,eAAC,CAAC8B,OAAO,CAAC4E,KAAK,EAAE;IACjC;EACF,CAAC,CAAC;AACJ"}
|