@sentry/wizard 4.8.0 → 4.9.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 +8 -0
- package/dist/e2e-tests/tests/angular-17.test.js +41 -41
- package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
- package/dist/e2e-tests/tests/angular-19.test.js +39 -39
- package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
- package/dist/e2e-tests/tests/expo.test.js +10 -2
- package/dist/e2e-tests/tests/expo.test.js.map +1 -1
- package/dist/e2e-tests/tests/react-native.test.js +38 -3
- package/dist/e2e-tests/tests/react-native.test.js.map +1 -1
- package/dist/e2e-tests/utils/index.js +14 -6
- package/dist/e2e-tests/utils/index.js.map +1 -1
- package/dist/lib/Helper/SentryCli.d.ts +0 -11
- package/dist/lib/Helper/SentryCli.js +0 -52
- package/dist/lib/Helper/SentryCli.js.map +1 -1
- package/dist/src/android/templates.js +2 -0
- package/dist/src/android/templates.js.map +1 -1
- package/dist/src/angular/angular-wizard.js +1 -1
- package/dist/src/angular/angular-wizard.js.map +1 -1
- package/dist/src/angular/sdk-setup.d.ts +1 -1
- package/dist/src/angular/sdk-setup.js +3 -3
- package/dist/src/angular/sdk-setup.js.map +1 -1
- package/dist/src/apple/code-tools.d.ts +4 -2
- package/dist/src/apple/code-tools.js +21 -11
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/inject-code-snippet.js +5 -3
- package/dist/src/apple/inject-code-snippet.js.map +1 -1
- package/dist/src/apple/macos-system-helper.d.ts +5 -0
- package/dist/src/apple/macos-system-helper.js +86 -0
- package/dist/src/apple/macos-system-helper.js.map +1 -0
- package/dist/src/apple/templates.js +10 -0
- package/dist/src/apple/templates.js.map +1 -1
- package/dist/src/apple/xcode-manager.d.ts +237 -11
- package/dist/src/apple/xcode-manager.js +736 -65
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/apple/xcode-project-object-with-id.d.ts +5 -0
- package/dist/src/apple/xcode-project-object-with-id.js +3 -0
- package/dist/src/apple/xcode-project-object-with-id.js.map +1 -0
- package/dist/src/flutter/templates.js +7 -1
- package/dist/src/flutter/templates.js.map +1 -1
- package/dist/src/nextjs/nextjs-wizard.js +1 -3
- package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
- package/dist/src/nuxt/nuxt-wizard.js +1 -3
- package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
- package/dist/src/react-native/expo-env-file.js +5 -0
- package/dist/src/react-native/expo-env-file.js.map +1 -1
- package/dist/src/react-native/expo-metro.js +18 -5
- package/dist/src/react-native/expo-metro.js.map +1 -1
- package/dist/src/react-native/expo.js +6 -0
- package/dist/src/react-native/expo.js.map +1 -1
- package/dist/src/react-native/glob.js +14 -4
- package/dist/src/react-native/glob.js.map +1 -1
- package/dist/src/react-native/gradle.js +14 -4
- package/dist/src/react-native/gradle.js.map +1 -1
- package/dist/src/react-native/javascript.d.ts +9 -4
- package/dist/src/react-native/javascript.js +44 -22
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/metro.d.ts +1 -1
- package/dist/src/react-native/metro.js +30 -4
- package/dist/src/react-native/metro.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.d.ts +4 -0
- package/dist/src/react-native/react-native-wizard.js +32 -4
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-native/xcode.js +24 -9
- package/dist/src/react-native/xcode.js.map +1 -1
- package/dist/src/remix/remix-wizard.js +1 -3
- package/dist/src/remix/remix-wizard.js.map +1 -1
- package/dist/src/sveltekit/sveltekit-wizard.js +1 -3
- package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
- package/dist/src/utils/clack/index.d.ts +2 -12
- package/dist/src/utils/clack/index.js +8 -47
- package/dist/src/utils/clack/index.js.map +1 -1
- package/dist/src/utils/git.d.ts +11 -0
- package/dist/src/utils/git.js +69 -0
- package/dist/src/utils/git.js.map +1 -0
- package/dist/src/utils/sentrycli-utils.js +13 -4
- package/dist/src/utils/sentrycli-utils.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/test/apple/code-tools.test.js +54 -35
- package/dist/test/apple/code-tools.test.js.map +1 -1
- package/dist/test/apple/configure-sentry-cli.test.d.ts +1 -0
- package/dist/test/apple/configure-sentry-cli.test.js +131 -0
- package/dist/test/apple/configure-sentry-cli.test.js.map +1 -0
- package/dist/test/apple/macos-system-helper-mocked.test.d.ts +1 -0
- package/dist/test/apple/macos-system-helper-mocked.test.js +46 -0
- package/dist/test/apple/macos-system-helper-mocked.test.js.map +1 -0
- package/dist/test/apple/macos-system-helper.test.d.ts +1 -0
- package/dist/test/apple/macos-system-helper.test.js +88 -0
- package/dist/test/apple/macos-system-helper.test.js.map +1 -0
- package/dist/test/apple/templates.test.js +10 -0
- package/dist/test/apple/templates.test.js.map +1 -1
- package/dist/test/apple/xcode-manager.test.js +745 -379
- package/dist/test/apple/xcode-manager.test.js.map +1 -1
- package/dist/test/flutter/templates.test.js +9 -0
- package/dist/test/flutter/templates.test.js.map +1 -1
- package/dist/test/react-native/javascript.test.js +119 -0
- package/dist/test/react-native/javascript.test.js.map +1 -1
- package/dist/test/utils/git.test.d.ts +1 -0
- package/dist/test/utils/git.test.js +70 -0
- package/dist/test/utils/git.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -32,8 +32,10 @@ exports.XcodeProject = void 0;
|
|
|
32
32
|
const clack = __importStar(require("@clack/prompts"));
|
|
33
33
|
const fs = __importStar(require("node:fs"));
|
|
34
34
|
const path = __importStar(require("node:path"));
|
|
35
|
+
const debug_1 = require("../utils/debug");
|
|
35
36
|
const templates = __importStar(require("./templates"));
|
|
36
37
|
const xcode_1 = require("xcode");
|
|
38
|
+
const macos_system_helper_1 = require("./macos-system-helper");
|
|
37
39
|
function setDebugInformationFormatAndSandbox(proj, targetName) {
|
|
38
40
|
const xcObjects = proj.hash.project.objects;
|
|
39
41
|
if (!xcObjects.PBXNativeTarget) {
|
|
@@ -196,6 +198,7 @@ function addUploadSymbolsScript(xcodeProject, sentryProject, targetName, uploadS
|
|
|
196
198
|
}
|
|
197
199
|
xcObjects.PBXShellScriptBuildPhase[key] = value;
|
|
198
200
|
}
|
|
201
|
+
// Add the build phase to the target
|
|
199
202
|
const isHomebrewInstalled = fs.existsSync('/opt/homebrew/bin/sentry-cli');
|
|
200
203
|
xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Upload Debug Symbols to Sentry', targetKey, {
|
|
201
204
|
inputFileListPaths: [],
|
|
@@ -207,17 +210,32 @@ function addUploadSymbolsScript(xcodeProject, sentryProject, targetName, uploadS
|
|
|
207
210
|
clack.log.step(`Added Sentry upload script to "${targetName}" build phase`);
|
|
208
211
|
}
|
|
209
212
|
class XcodeProject {
|
|
210
|
-
|
|
213
|
+
/**
|
|
214
|
+
* The directory where the Xcode project is located.
|
|
215
|
+
*/
|
|
216
|
+
baseDir;
|
|
217
|
+
/**
|
|
218
|
+
* The path to the `<PROJECT>.xcodeproj` directory.
|
|
219
|
+
*/
|
|
220
|
+
xcodeprojPath;
|
|
221
|
+
/**
|
|
222
|
+
* The path to the `project.pbxproj` file.
|
|
223
|
+
*/
|
|
224
|
+
pbxprojPath;
|
|
225
|
+
/**
|
|
226
|
+
* The Xcode project object.
|
|
227
|
+
*/
|
|
211
228
|
project;
|
|
212
229
|
objects;
|
|
213
|
-
files;
|
|
214
230
|
/**
|
|
215
231
|
* Creates a new XcodeProject instance, a wrapper around the Xcode project file `<PROJECT>.xcodeproj/project.pbxproj`.
|
|
216
232
|
*
|
|
217
233
|
* @param projectPath - The path to the Xcode project file
|
|
218
234
|
*/
|
|
219
235
|
constructor(projectPath) {
|
|
220
|
-
this.
|
|
236
|
+
this.pbxprojPath = projectPath;
|
|
237
|
+
this.xcodeprojPath = path.dirname(projectPath);
|
|
238
|
+
this.baseDir = path.dirname(this.xcodeprojPath);
|
|
221
239
|
this.project = (0, xcode_1.project)(projectPath);
|
|
222
240
|
this.project.parseSync();
|
|
223
241
|
this.objects = this.project.hash.project.objects;
|
|
@@ -244,85 +262,738 @@ class XcodeProject {
|
|
|
244
262
|
addSentrySPM(this.project, target);
|
|
245
263
|
}
|
|
246
264
|
const newContent = this.project.writeSync();
|
|
247
|
-
fs.writeFileSync(this.
|
|
265
|
+
fs.writeFileSync(this.pbxprojPath, newContent);
|
|
248
266
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Retrieves all source files associated with a specific target in the Xcode project.
|
|
269
|
+
* This is used to find files where we can inject Sentry initialization code.
|
|
270
|
+
*
|
|
271
|
+
* @param targetName - The name of the target to get files for
|
|
272
|
+
* @returns An array of absolute file paths for the target's source files, or undefined if target not found
|
|
273
|
+
*/
|
|
274
|
+
getSourceFilesForTarget(targetName) {
|
|
275
|
+
// ## Summary how Xcode Projects are structured:
|
|
276
|
+
// - Every Xcode Project has exactly one main group of type `PBXGroup`
|
|
277
|
+
// - The main group contains a list of children identifiers
|
|
278
|
+
// - Each child can be a `PBXGroup`, a `PBXFileReference` or a `PBXFileSystemSynchronizedRootGroup`
|
|
279
|
+
// - Each `PBXGroup` has a list of children identifiers which again can be `PBXGroup`, `PBXFileReference` or `PBXFileSystemSynchronizedRootGroup`
|
|
280
|
+
// - The target defines the list of `fileSystemSynchronizedGroups` which are `PBXFileSystemSynchronizedRootGroup` to be included in the build phase
|
|
281
|
+
// - The `PBXFileSystemSynchronizedRootGroup` has a list of `exceptions` which are `PBXFileSystemSynchronizedBuildFileExceptionSet`
|
|
282
|
+
// - Each `PBXFileSystemSynchronizedBuildFileExceptionSet` represents a folder to be excluded from the build.
|
|
283
|
+
// - The `PBXFileSystemSynchronizedBuildFileExceptionSet` has a list of `membershipExceptions` which are files to be excluded from being excluded, therefore included in the build.
|
|
284
|
+
// - The Xcode project has a build phase `PBXSourcesBuildPhase` which has a list of `files` which are `PBXBuildFile`
|
|
285
|
+
// - A file which is not part of a `PBXFileSystemSynchronizedRootGroup` must be added to the `files` list of the `PBXSourcesBuildPhase` build phase
|
|
286
|
+
// - Nested subfolders in `fileSystemSynchronizedGroups` are not declared but recursively included
|
|
287
|
+
//
|
|
288
|
+
// Based on the findings above the files included in the build phase are:
|
|
289
|
+
// - All files in the `files` of the `PBXSourcesBuildPhase` build phase `Sources` of the target
|
|
290
|
+
// - All files in directories of the `fileSystemSynchronizedGroups` of the target
|
|
291
|
+
// - Excluding all files in the `exceptions` of the `PBXFileSystemSynchronizedRootGroup` of the target
|
|
292
|
+
// - Including all files in the `membershipExceptions` of the `PBXFileSystemSynchronizedBuildFileExceptionSet` of the target
|
|
293
|
+
const nativeTarget = this.findNativeTargetByName(targetName);
|
|
294
|
+
if (!nativeTarget) {
|
|
295
|
+
(0, debug_1.debug)('Target not found: ' + targetName);
|
|
263
296
|
return undefined;
|
|
264
297
|
}
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
298
|
+
const filesInBuildPhase = this.findFilesInSourceBuildPhase(nativeTarget);
|
|
299
|
+
(0, debug_1.debug)(`Found ${filesInBuildPhase.length} files in build phase for target: ${targetName}`);
|
|
300
|
+
const filesInSynchronizedRootGroups = this.findFilesInSynchronizedRootGroups(nativeTarget);
|
|
301
|
+
(0, debug_1.debug)(`Found ${filesInSynchronizedRootGroups.length} files in synchronized root groups for target: ${targetName}`);
|
|
302
|
+
return [...filesInBuildPhase, ...filesInSynchronizedRootGroups];
|
|
303
|
+
}
|
|
304
|
+
// ================================ TARGET HELPERS ================================
|
|
305
|
+
/**
|
|
306
|
+
* Finds a native target by name.
|
|
307
|
+
*
|
|
308
|
+
* @param targetName - The name of the target to find
|
|
309
|
+
* @returns The native target, or undefined if the target is not found
|
|
310
|
+
*/
|
|
311
|
+
findNativeTargetByName(targetName) {
|
|
312
|
+
(0, debug_1.debug)('Finding native target by name: ' + targetName);
|
|
313
|
+
if (!this.objects.PBXNativeTarget) {
|
|
314
|
+
(0, debug_1.debug)('No native targets found');
|
|
269
315
|
return undefined;
|
|
270
316
|
}
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const fileRef = this.objects.PBXBuildFile?.[file.value]?.fileRef;
|
|
277
|
-
if (!fileRef) {
|
|
278
|
-
return '';
|
|
317
|
+
const nativeTargets = Object.entries(this.objects.PBXNativeTarget);
|
|
318
|
+
for (const [key, target] of nativeTargets) {
|
|
319
|
+
// Ignore comments
|
|
320
|
+
if (key.endsWith('_comment') || typeof target === 'string') {
|
|
321
|
+
continue;
|
|
279
322
|
}
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
|
|
323
|
+
// Ignore targets that are not the target we are looking for
|
|
324
|
+
if (target.name !== targetName) {
|
|
325
|
+
continue;
|
|
283
326
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
327
|
+
(0, debug_1.debug)('Found native target: ' + targetName);
|
|
328
|
+
return {
|
|
329
|
+
id: key,
|
|
330
|
+
obj: target,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
(0, debug_1.debug)('Target not found: ' + targetName);
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
// ================================ BUILD PHASE HELPERS ================================
|
|
337
|
+
/**
|
|
338
|
+
* Finds the source build phase in a target.
|
|
339
|
+
*
|
|
340
|
+
* @param target - The target to find the source build phase in
|
|
341
|
+
* @returns The source build phase, or undefined if the target is not found or has no source build phase
|
|
342
|
+
*/
|
|
343
|
+
findSourceBuildPhaseInTarget(target) {
|
|
344
|
+
(0, debug_1.debug)(`Finding source build phase in target: ${target.name}`);
|
|
345
|
+
if (!target.buildPhases) {
|
|
346
|
+
(0, debug_1.debug)('No build phases found for target: ' + target.name);
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
for (const phase of target.buildPhases) {
|
|
350
|
+
const buildPhaseId = phase.value;
|
|
351
|
+
const buildPhase = this.objects.PBXSourcesBuildPhase?.[buildPhaseId];
|
|
352
|
+
if (typeof buildPhase !== 'object') {
|
|
353
|
+
// Ignore comments
|
|
354
|
+
continue;
|
|
295
355
|
}
|
|
296
|
-
|
|
356
|
+
(0, debug_1.debug)(`Found source build phase: ${buildPhaseId} for target: ${target.name}`);
|
|
357
|
+
return {
|
|
358
|
+
id: buildPhaseId,
|
|
359
|
+
obj: buildPhase,
|
|
360
|
+
};
|
|
297
361
|
}
|
|
298
|
-
|
|
362
|
+
(0, debug_1.debug)(`No source build phase found for target: ${target.name}`);
|
|
363
|
+
return undefined;
|
|
299
364
|
}
|
|
300
|
-
|
|
365
|
+
// ================================ FILE HELPERS ================================
|
|
366
|
+
/**
|
|
367
|
+
* Finds all files in the source build phase of a target.
|
|
368
|
+
*
|
|
369
|
+
* @param nativeTarget - The target to find the files in
|
|
370
|
+
* @returns The files in the source build phase of the target, or an empty array if the target is not found or has no source build phase
|
|
371
|
+
*/
|
|
372
|
+
findFilesInSourceBuildPhase(nativeTarget) {
|
|
373
|
+
(0, debug_1.debug)('Finding files in source build phase for target: ' +
|
|
374
|
+
nativeTarget.obj.name);
|
|
375
|
+
const buildPhase = this.findSourceBuildPhaseInTarget(nativeTarget.obj);
|
|
376
|
+
if (!buildPhase) {
|
|
377
|
+
(0, debug_1.debug)(`Sources build phase not found for target: ${nativeTarget.obj.name}`);
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
const buildPhaseFiles = buildPhase.obj.files;
|
|
381
|
+
if (!buildPhaseFiles) {
|
|
382
|
+
(0, debug_1.debug)(`No files found in sources build phase for target: ${nativeTarget.obj.name}`);
|
|
383
|
+
return [];
|
|
384
|
+
}
|
|
385
|
+
if (!this.objects.PBXBuildFile) {
|
|
386
|
+
(0, debug_1.debug)('PBXBuildFile is undefined');
|
|
387
|
+
return [];
|
|
388
|
+
}
|
|
389
|
+
if (!this.objects.PBXFileReference) {
|
|
390
|
+
(0, debug_1.debug)('PBXFileReference is undefined');
|
|
391
|
+
return [];
|
|
392
|
+
}
|
|
301
393
|
const result = [];
|
|
302
|
-
for (const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
394
|
+
for (const file of buildPhaseFiles) {
|
|
395
|
+
(0, debug_1.debug)(`Resolving build phase file: ${file.value}`);
|
|
396
|
+
// Find the related build file object
|
|
397
|
+
const buildFileObj = this.objects.PBXBuildFile[file.value];
|
|
398
|
+
if (!buildFileObj || typeof buildFileObj !== 'object') {
|
|
399
|
+
(0, debug_1.debug)(`Build file object not found for file: ${file.value}`);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
(0, debug_1.debug)(`Build file object found for file: ${file.value}`);
|
|
403
|
+
const buildFileRefId = buildFileObj.fileRef;
|
|
404
|
+
if (!buildFileRefId) {
|
|
405
|
+
(0, debug_1.debug)(`File reference not found for file: ${file.value}`);
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
(0, debug_1.debug)(`Build file reference found for file: ${file.value}`);
|
|
409
|
+
// Find the related file reference object
|
|
410
|
+
const buildFile = this.objects.PBXFileReference[buildFileRefId];
|
|
411
|
+
if (!buildFile || typeof buildFile !== 'object') {
|
|
412
|
+
(0, debug_1.debug)(`File not found in file dictionary for file: ${file.value}`);
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
(0, debug_1.debug)(`Build file found in file dictionary for file: ${file.value}`);
|
|
416
|
+
// Resolve the path of the file based on the `sourceTree` property
|
|
417
|
+
const resolvedFilePath = this.resolveAbsolutePathOfFileReference({
|
|
418
|
+
id: buildFileRefId,
|
|
419
|
+
obj: buildFile,
|
|
420
|
+
});
|
|
421
|
+
if (!resolvedFilePath) {
|
|
422
|
+
(0, debug_1.debug)(`Failed to resolve file path for file: ${file.value}`);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
(0, debug_1.debug)(`Resolved file ${file.value} to path: ${resolvedFilePath}`);
|
|
426
|
+
result.push(resolvedFilePath);
|
|
427
|
+
}
|
|
428
|
+
(0, debug_1.debug)(`Resolved ${result.length} files for target: ${nativeTarget.obj.name}`);
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Resolves the absolute path of a file reference.
|
|
433
|
+
*
|
|
434
|
+
* @param fileRef - The file reference to resolve the path of
|
|
435
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
436
|
+
*/
|
|
437
|
+
resolveAbsolutePathOfFileReference(fileRef) {
|
|
438
|
+
(0, debug_1.debug)(`Resolving path of file reference: ${fileRef.id} with path: ${fileRef.obj.path}`);
|
|
439
|
+
// File path is expected to be set, therefore typing is non-nullable.
|
|
440
|
+
// As the file is loaded from a project file, it is not guaranteed to be set,
|
|
441
|
+
// therefore we treat it as optional.
|
|
442
|
+
if (!fileRef.obj.path) {
|
|
443
|
+
(0, debug_1.debug)(`File reference path not found for file reference: ${fileRef.id}`);
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
// File references are resolved based on the `sourceTree` property
|
|
447
|
+
// which can have one of the following values:
|
|
448
|
+
// - '<absolute>': The file path is absolute
|
|
449
|
+
// - '<group>': The file path is relative to the parent group of the file reference
|
|
450
|
+
// - 'BUILT_PRODUCTS_DIR': The file path is relative to the built products directory, i.e. the build output directory in derived data
|
|
451
|
+
// - 'SOURCE_ROOT': The file path is relative to the source root, i.e. the directory where the Xcode project is located
|
|
452
|
+
// - 'SDKROOT': The file path is relative to the SDK root, i.e. the directory where the SDK is installed
|
|
453
|
+
// - 'DEVELOPER_DIR': The file path is relative to the developer directory, i.e. the directory where the Xcode command line tools are installed
|
|
454
|
+
// The default is '<group>'
|
|
455
|
+
const fileRefSourceTree = fileRef.obj.sourceTree?.replace(/"/g, '') ?? '';
|
|
456
|
+
switch (fileRefSourceTree) {
|
|
457
|
+
case '<absolute>':
|
|
458
|
+
return fileRef.obj.path.replace(/"/g, '');
|
|
459
|
+
case '<group>':
|
|
460
|
+
return this.resolveAbsoluteFilePathRelativeToGroup(fileRef);
|
|
461
|
+
case 'BUILT_PRODUCTS_DIR':
|
|
462
|
+
return this.resolveAbsoluteFilePathRelativeToBuiltProductsDir(fileRef);
|
|
463
|
+
case 'SOURCE_ROOT':
|
|
464
|
+
return this.resolveAbsoluteFilePathRelativeToSourceRoot(fileRef);
|
|
465
|
+
case 'SDKROOT':
|
|
466
|
+
return this.resolveAbsoluteFilePathRelativeToSdkRoot(fileRef);
|
|
467
|
+
case 'DEVELOPER_DIR':
|
|
468
|
+
return this.resolveAbsoluteFilePathRelativeToDeveloperDir(fileRef);
|
|
469
|
+
default:
|
|
470
|
+
(0, debug_1.debug)(`Unknown source tree '${fileRef.obj.sourceTree}' for build file: ${fileRef.obj.path}`);
|
|
471
|
+
return undefined;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Resolves the absolute path of a file reference relative to the parent group.
|
|
476
|
+
*
|
|
477
|
+
* @param fileRef - The file reference to resolve the path of
|
|
478
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
479
|
+
*/
|
|
480
|
+
resolveAbsoluteFilePathRelativeToGroup(fileRef) {
|
|
481
|
+
(0, debug_1.debug)(`Resolving absolute file path relative to group for file reference: ${fileRef.id} with path: ${fileRef.obj.path ?? ''}`);
|
|
482
|
+
const fileRefPath = fileRef.obj.path?.replace(/"/g, '');
|
|
483
|
+
if (!fileRefPath) {
|
|
484
|
+
(0, debug_1.debug)(`File reference path not found for file reference: ${fileRef.id}`);
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
// Find the parent group of the file reference by searching for the reverse relationship
|
|
488
|
+
const parentGroup = this.findParentGroupByChildId(fileRef.id);
|
|
489
|
+
if (!parentGroup) {
|
|
490
|
+
(0, debug_1.debug)(`Parent group not found for file reference: ${fileRef.id} at path: ${fileRefPath}`);
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
// Resolve the path of the parent group
|
|
494
|
+
const absoluteGroupPath = this.resolveAbsolutePathOfGroup(parentGroup);
|
|
495
|
+
if (!absoluteGroupPath) {
|
|
496
|
+
(0, debug_1.debug)(`Failed to resolve path of group: ${parentGroup.id}`);
|
|
497
|
+
return undefined;
|
|
498
|
+
}
|
|
499
|
+
return path.join(absoluteGroupPath, fileRefPath);
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Resolves the absolute path of a file reference relative to the built products directory.
|
|
503
|
+
*
|
|
504
|
+
* @param buildFile - The file reference to resolve the path of
|
|
505
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
506
|
+
*/
|
|
507
|
+
resolveAbsoluteFilePathRelativeToBuiltProductsDir(buildFile) {
|
|
508
|
+
(0, debug_1.debug)(`Resolving absolute file path relative to built products directory for file reference: ${buildFile.id} with path: ${buildFile.obj.path ?? ''}`);
|
|
509
|
+
const builtProductsDir = this.getBuildProductsDirectoryPath();
|
|
510
|
+
if (!builtProductsDir) {
|
|
511
|
+
(0, debug_1.debug)(`Failed to resolve built products directory path`);
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
return path.join(builtProductsDir, buildFile.obj.path.replace(/"/g, ''));
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Resolves the absolute path of a file reference relative to the source root.
|
|
518
|
+
*
|
|
519
|
+
* The source root is the directory where the `.xcodeproj` file is located.
|
|
520
|
+
*
|
|
521
|
+
* @param buildFile - The file reference to resolve the path of
|
|
522
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
523
|
+
*/
|
|
524
|
+
resolveAbsoluteFilePathRelativeToSourceRoot(buildFile) {
|
|
525
|
+
return path.join(this.baseDir, buildFile.obj.path.replace(/"/g, ''));
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Resolves the absolute path of a file reference relative to the SDK root.
|
|
529
|
+
*
|
|
530
|
+
* @param buildFile - The file reference to resolve the path of
|
|
531
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
532
|
+
*/
|
|
533
|
+
resolveAbsoluteFilePathRelativeToSdkRoot(buildFile) {
|
|
534
|
+
(0, debug_1.debug)(`Resolving absolute file path relative to SDK root for file reference: ${buildFile.id} with path: ${buildFile.obj.path ?? ''}`);
|
|
535
|
+
const sdkRoot = macos_system_helper_1.MacOSSystemHelpers.findSDKRootDirectoryPath();
|
|
536
|
+
if (!sdkRoot) {
|
|
537
|
+
(0, debug_1.debug)(`Failed to resolve SDK root directory path`);
|
|
538
|
+
return undefined;
|
|
539
|
+
}
|
|
540
|
+
return path.join(sdkRoot, buildFile.obj.path.replace(/"/g, ''));
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Resolves the absolute path of a file reference relative to the developer directory.
|
|
544
|
+
*
|
|
545
|
+
* @param buildFile - The file reference to resolve the path of
|
|
546
|
+
* @returns The absolute path of the file reference, or undefined if the file reference is not found or has no path
|
|
547
|
+
*/
|
|
548
|
+
resolveAbsoluteFilePathRelativeToDeveloperDir(buildFile) {
|
|
549
|
+
(0, debug_1.debug)(`Resolving absolute file path relative to developer directory for file reference: ${buildFile.id} with path: ${buildFile.obj.path ?? ''}`);
|
|
550
|
+
const developerDir = macos_system_helper_1.MacOSSystemHelpers.findDeveloperDirectoryPath();
|
|
551
|
+
if (!developerDir) {
|
|
552
|
+
(0, debug_1.debug)(`Failed to resolve developer directory path`);
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
return path.join(developerDir, buildFile.obj.path.replace(/"/g, ''));
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Resolves the absolute path of a group.
|
|
559
|
+
*
|
|
560
|
+
* @param group - The group to resolve the path of
|
|
561
|
+
* @returns The absolute path of the group, or undefined if the group is not found or has no path
|
|
562
|
+
*/
|
|
563
|
+
resolveAbsolutePathOfGroup(group) {
|
|
564
|
+
(0, debug_1.debug)(`Resolving path of group: ${group.id} with path: ${group.obj.path ?? ''}`);
|
|
565
|
+
// Group paths are resolved based on the `sourceTree` property
|
|
566
|
+
// which can have one of the following values:
|
|
567
|
+
// - '<group>': The group path is relative to the parent group of the group
|
|
568
|
+
// - 'SOURCE_ROOT': The group path is relative to the source root, i.e. the directory where the Xcode project is located
|
|
569
|
+
// - 'BUILT_PRODUCTS_DIR': The group path is relative to the built products directory, i.e. the build output directory in derived data
|
|
570
|
+
// - 'SDKROOT': The group path is relative to the SDK root, i.e. the directory where the SDK is installed
|
|
571
|
+
// - 'DEVELOPER_DIR': The group path is relative to the developer directory, i.e. the directory where the Xcode command line tools are installed
|
|
572
|
+
// The default is '<group>'
|
|
573
|
+
const groupSourceTree = group.obj.sourceTree?.replace(/"/g, '') ?? '<group>';
|
|
574
|
+
switch (groupSourceTree) {
|
|
575
|
+
case '<group>':
|
|
576
|
+
return this.resolvePathOfGroupRelativeToGroup(group);
|
|
577
|
+
case 'SOURCE_ROOT':
|
|
578
|
+
return this.resolvePathOfGroupRelativeToSourceRoot(group);
|
|
579
|
+
case 'BUILT_PRODUCTS_DIR':
|
|
580
|
+
return this.resolvePathOfGroupRelativeToBuiltProductsDir(group);
|
|
581
|
+
case 'SDKROOT':
|
|
582
|
+
return this.resolvePathOfGroupRelativeToSdkRoot(group);
|
|
583
|
+
case 'DEVELOPER_DIR':
|
|
584
|
+
return this.resolvePathOfGroupRelativeToDeveloperDir(group);
|
|
585
|
+
default:
|
|
586
|
+
(0, debug_1.debug)(`Unknown source tree '${groupSourceTree}' for group: ${group.id}`);
|
|
587
|
+
return undefined;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Resolves the path of a group relative to the parent group.
|
|
592
|
+
*
|
|
593
|
+
* @param group - The group to resolve the path of
|
|
594
|
+
* @returns The path of the group relative to the parent group, or undefined if the group is not found or has no path
|
|
595
|
+
*/
|
|
596
|
+
resolvePathOfGroupRelativeToGroup(group) {
|
|
597
|
+
const parentGroup = this.findParentGroupByChildId(group.id);
|
|
598
|
+
if (!parentGroup) {
|
|
599
|
+
(0, debug_1.debug)(`Parent group not found for group: ${group.id}`);
|
|
600
|
+
// If the parent group is not found, check if the group is the main group
|
|
601
|
+
// We assume the main group is at the root of the project
|
|
602
|
+
if (this.isMainGroup(group.id)) {
|
|
603
|
+
return this.baseDir;
|
|
604
|
+
}
|
|
605
|
+
return undefined;
|
|
606
|
+
}
|
|
607
|
+
const parentGroupPath = this.resolveAbsolutePathOfGroup(parentGroup);
|
|
608
|
+
if (!parentGroupPath) {
|
|
609
|
+
(0, debug_1.debug)(`Failed to resolve path of parent group: ${parentGroup.id}`);
|
|
610
|
+
return undefined;
|
|
611
|
+
}
|
|
612
|
+
const groupPath = group.obj.path?.replace(/"/g, '') ?? '';
|
|
613
|
+
if (!groupPath) {
|
|
614
|
+
(0, debug_1.debug)(`Group path not found for group: ${group.id}`);
|
|
615
|
+
return undefined;
|
|
616
|
+
}
|
|
617
|
+
return path.join(parentGroupPath, groupPath);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Resolves the path of a group relative to the source root.
|
|
621
|
+
*
|
|
622
|
+
* The source root is the directory where the `.xcodeproj` file is located.
|
|
623
|
+
*
|
|
624
|
+
* @param group - The group to resolve the path of
|
|
625
|
+
* @returns The path of the group relative to the source root, or undefined if the group is not found or has no path
|
|
626
|
+
*/
|
|
627
|
+
resolvePathOfGroupRelativeToSourceRoot(group) {
|
|
628
|
+
const groupPath = group.obj.path?.replace(/"/g, '') ?? '';
|
|
629
|
+
if (!groupPath) {
|
|
630
|
+
(0, debug_1.debug)(`Group path not found for group: ${group.id}`);
|
|
631
|
+
return this.baseDir;
|
|
632
|
+
}
|
|
633
|
+
return path.join(this.baseDir, groupPath);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Resolves the path of a group relative to the built products directory.
|
|
637
|
+
*
|
|
638
|
+
* @param group - The group to resolve the path of
|
|
639
|
+
* @returns The path of the group relative to the built products directory, or undefined if the group is not found or has no path
|
|
640
|
+
*/
|
|
641
|
+
resolvePathOfGroupRelativeToBuiltProductsDir(group) {
|
|
642
|
+
(0, debug_1.debug)(`Resolving path of group: ${group.id} relative to built products directory`);
|
|
643
|
+
const builtProductsDir = this.getBuildProductsDirectoryPath();
|
|
644
|
+
if (!builtProductsDir) {
|
|
645
|
+
(0, debug_1.debug)(`Failed to resolve built products directory path`);
|
|
646
|
+
return undefined;
|
|
647
|
+
}
|
|
648
|
+
return path.join(builtProductsDir, group.obj.path?.replace(/"/g, '') ?? '');
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Resolves the path of a group relative to the SDK root.
|
|
652
|
+
*
|
|
653
|
+
* The SDK root is the directory where the SDK is installed.
|
|
654
|
+
*
|
|
655
|
+
* @param group - The group to resolve the path of
|
|
656
|
+
* @returns The path of the group relative to the SDK root, or undefined if the group is not found or has no path
|
|
657
|
+
*/
|
|
658
|
+
resolvePathOfGroupRelativeToSdkRoot(group) {
|
|
659
|
+
(0, debug_1.debug)(`Resolving path of group: ${group.id} relative to SDK root`);
|
|
660
|
+
const sdkRoot = macos_system_helper_1.MacOSSystemHelpers.findSDKRootDirectoryPath();
|
|
661
|
+
if (!sdkRoot) {
|
|
662
|
+
(0, debug_1.debug)(`Failed to resolve SDK root directory path`);
|
|
663
|
+
return undefined;
|
|
664
|
+
}
|
|
665
|
+
return path.join(sdkRoot, group.obj.path?.replace(/"/g, '') ?? '');
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Resolves the path of a group relative to the developer directory.
|
|
669
|
+
*
|
|
670
|
+
* The developer directory is the directory where the Xcode command line tools are installed.
|
|
671
|
+
*
|
|
672
|
+
* @param group - The group to resolve the path of
|
|
673
|
+
* @returns The path of the group relative to the developer directory, or undefined if the group is not found or has no path
|
|
674
|
+
*/
|
|
675
|
+
resolvePathOfGroupRelativeToDeveloperDir(group) {
|
|
676
|
+
(0, debug_1.debug)(`Resolving path of group: ${group.id} relative to developer directory`);
|
|
677
|
+
const developerDir = macos_system_helper_1.MacOSSystemHelpers.findDeveloperDirectoryPath();
|
|
678
|
+
if (!developerDir) {
|
|
679
|
+
(0, debug_1.debug)(`Failed to resolve developer directory path`);
|
|
680
|
+
return undefined;
|
|
681
|
+
}
|
|
682
|
+
return path.join(developerDir, group.obj.path?.replace(/"/g, '') ?? '');
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Resolves the absolute path of a group.
|
|
686
|
+
*
|
|
687
|
+
* @param group - The group to resolve the path of
|
|
688
|
+
* @returns The absolute path of the group, or undefined if the group is not found or has no path
|
|
689
|
+
*/
|
|
690
|
+
resolveAbsolutePathOfSynchronizedRootGroup(group) {
|
|
691
|
+
(0, debug_1.debug)(`Resolving path of synchronized root group: ${group.id} with path: ${group.obj.path ?? ''}`);
|
|
692
|
+
// Group paths are resolved based on the `sourceTree` property
|
|
693
|
+
// which can have one of the following values:
|
|
694
|
+
// - '<group>': The group path is relative to the parent group of the group
|
|
695
|
+
// - 'SOURCE_ROOT': The group path is relative to the source root, i.e. the directory where the Xcode project is located
|
|
696
|
+
// - 'BUILT_PRODUCTS_DIR': The group path is relative to the built products directory, i.e. the build output directory in derived data
|
|
697
|
+
// - 'SDKROOT': The group path is relative to the SDK root, i.e. the directory where the SDK is installed
|
|
698
|
+
// - 'DEVELOPER_DIR': The group path is relative to the developer directory, i.e. the directory where the Xcode command line tools are installed
|
|
699
|
+
// The default is '<group>'
|
|
700
|
+
const groupSourceTree = group.obj.sourceTree?.replace(/"/g, '') ?? '<group>';
|
|
701
|
+
switch (groupSourceTree) {
|
|
702
|
+
case '<group>':
|
|
703
|
+
return this.resolvePathOfSynchronizedRootGroupRelativeToGroup(group);
|
|
704
|
+
case 'SOURCE_ROOT':
|
|
705
|
+
return this.resolvePathOfSynchronizedRootGroupRelativeToSourceRoot(group);
|
|
706
|
+
case 'BUILT_PRODUCTS_DIR':
|
|
707
|
+
return this.resolvePathOfSynchronizedRootGroupRelativeToBuiltProductsDir(group);
|
|
708
|
+
case 'SDKROOT':
|
|
709
|
+
return this.resolvePathOfSynchronizedRootGroupRelativeToSdkRoot(group);
|
|
710
|
+
case 'DEVELOPER_DIR':
|
|
711
|
+
return this.resolvePathOfSynchronizedRootGroupRelativeToDeveloperDir(group);
|
|
712
|
+
default:
|
|
713
|
+
(0, debug_1.debug)(`Unknown source tree '${groupSourceTree}' for group: ${group.id}`);
|
|
714
|
+
return undefined;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Resolves the path of a group relative to the parent group.
|
|
719
|
+
*
|
|
720
|
+
* @param group - The group to resolve the path of
|
|
721
|
+
* @returns The path of the group relative to the parent group, or undefined if the group is not found or has no path
|
|
722
|
+
*/
|
|
723
|
+
resolvePathOfSynchronizedRootGroupRelativeToGroup(group) {
|
|
724
|
+
const parentGroup = this.findParentGroupByChildId(group.id);
|
|
725
|
+
if (!parentGroup) {
|
|
726
|
+
(0, debug_1.debug)(`Parent group not found for group: ${group.id}`);
|
|
727
|
+
// If the parent group is not found, check if the group is the main group
|
|
728
|
+
// We assume the main group is at the root of the project
|
|
729
|
+
if (this.isMainGroup(group.id)) {
|
|
730
|
+
return this.baseDir;
|
|
731
|
+
}
|
|
732
|
+
return undefined;
|
|
733
|
+
}
|
|
734
|
+
const parentGroupPath = this.resolveAbsolutePathOfGroup(parentGroup);
|
|
735
|
+
if (!parentGroupPath) {
|
|
736
|
+
(0, debug_1.debug)(`Failed to resolve path of parent group: ${parentGroup.id}`);
|
|
737
|
+
return undefined;
|
|
738
|
+
}
|
|
739
|
+
const groupPath = group.obj.path?.replace(/"/g, '') ?? '';
|
|
740
|
+
if (!groupPath) {
|
|
741
|
+
(0, debug_1.debug)(`Group path not found for group: ${group.id}`);
|
|
742
|
+
return undefined;
|
|
743
|
+
}
|
|
744
|
+
return path.join(parentGroupPath, groupPath);
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Resolves the path of a group relative to the source root.
|
|
748
|
+
*
|
|
749
|
+
* The source root is the directory where the `.xcodeproj` file is located.
|
|
750
|
+
*
|
|
751
|
+
* @param group - The group to resolve the path of
|
|
752
|
+
* @returns The path of the group relative to the source root, or undefined if the group is not found or has no path
|
|
753
|
+
*/
|
|
754
|
+
resolvePathOfSynchronizedRootGroupRelativeToSourceRoot(group) {
|
|
755
|
+
const groupPath = group.obj.path?.replace(/"/g, '') ?? '';
|
|
756
|
+
if (!groupPath) {
|
|
757
|
+
(0, debug_1.debug)(`Group path not found for group: ${group.id}`);
|
|
758
|
+
return this.baseDir;
|
|
759
|
+
}
|
|
760
|
+
return path.join(this.baseDir, groupPath);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Resolves the path of a group relative to the built products directory.
|
|
764
|
+
*
|
|
765
|
+
* @param group - The group to resolve the path of
|
|
766
|
+
* @returns The path of the group relative to the built products directory, or undefined if the group is not found or has no path
|
|
767
|
+
*/
|
|
768
|
+
resolvePathOfSynchronizedRootGroupRelativeToBuiltProductsDir(group) {
|
|
769
|
+
(0, debug_1.debug)(`Resolving path of synchronized root group: ${group.id} relative to built products directory`);
|
|
770
|
+
const builtProductsDir = this.getBuildProductsDirectoryPath();
|
|
771
|
+
if (!builtProductsDir) {
|
|
772
|
+
(0, debug_1.debug)(`Failed to resolve built products directory path`);
|
|
773
|
+
return undefined;
|
|
774
|
+
}
|
|
775
|
+
return path.join(builtProductsDir, group.obj.path?.replace(/"/g, '') ?? '');
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Resolves the path of a group relative to the SDK root.
|
|
779
|
+
*
|
|
780
|
+
* The SDK root is the directory where the SDK is installed.
|
|
781
|
+
*
|
|
782
|
+
* @param group - The group to resolve the path of
|
|
783
|
+
* @returns The path of the group relative to the SDK root, or undefined if the group is not found or has no path
|
|
784
|
+
*/
|
|
785
|
+
resolvePathOfSynchronizedRootGroupRelativeToSdkRoot(group) {
|
|
786
|
+
(0, debug_1.debug)(`Resolving path of group: ${group.id} relative to SDK root`);
|
|
787
|
+
const sdkRoot = macos_system_helper_1.MacOSSystemHelpers.findSDKRootDirectoryPath();
|
|
788
|
+
if (!sdkRoot) {
|
|
789
|
+
(0, debug_1.debug)(`Failed to resolve SDK root directory path`);
|
|
790
|
+
return undefined;
|
|
791
|
+
}
|
|
792
|
+
return path.join(sdkRoot, group.obj.path?.replace(/"/g, '') ?? '');
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Resolves the path of a group relative to the developer directory.
|
|
796
|
+
*
|
|
797
|
+
* The developer directory is the directory where the Xcode command line tools are installed.
|
|
798
|
+
*
|
|
799
|
+
* @param group - The group to resolve the path of
|
|
800
|
+
* @returns The path of the group relative to the developer directory, or undefined if the group is not found or has no path
|
|
801
|
+
*/
|
|
802
|
+
resolvePathOfSynchronizedRootGroupRelativeToDeveloperDir(group) {
|
|
803
|
+
(0, debug_1.debug)(`Resolving path of synchronized root group: ${group.id} relative to developer directory`);
|
|
804
|
+
const developerDir = macos_system_helper_1.MacOSSystemHelpers.findDeveloperDirectoryPath();
|
|
805
|
+
if (!developerDir) {
|
|
806
|
+
(0, debug_1.debug)(`Failed to resolve developer directory path`);
|
|
807
|
+
return undefined;
|
|
808
|
+
}
|
|
809
|
+
return path.join(developerDir, group.obj.path?.replace(/"/g, '') ?? '');
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Finds all files in the synchronized root groups of a target.
|
|
813
|
+
*
|
|
814
|
+
* @param nativeTarget - The target to find the files in
|
|
815
|
+
* @returns The files in the synchronized root groups of the target, or an empty array if the target is not found or has no synchronized root groups
|
|
816
|
+
*/
|
|
817
|
+
findFilesInSynchronizedRootGroups(nativeTarget) {
|
|
818
|
+
(0, debug_1.debug)(`Finding files in synchronized root groups for target: ${nativeTarget.obj.name}`);
|
|
819
|
+
const synchronizedRootGroups = nativeTarget.obj.fileSystemSynchronizedGroups ?? [];
|
|
820
|
+
const result = [];
|
|
821
|
+
for (const group of synchronizedRootGroups) {
|
|
822
|
+
const groupObj = this.objects.PBXFileSystemSynchronizedRootGroup?.[group.value];
|
|
823
|
+
if (!groupObj || typeof groupObj !== 'object') {
|
|
824
|
+
(0, debug_1.debug)(`Synchronized root group not found: ${group.value}`);
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
(0, debug_1.debug)(`Found synchronized root group: ${group.value}`);
|
|
828
|
+
const files = this.getFilesInSynchronizedRootGroup({
|
|
829
|
+
id: group.value,
|
|
830
|
+
obj: groupObj,
|
|
831
|
+
});
|
|
832
|
+
(0, debug_1.debug)(`Found ${files.length} files in synchronized root group: ${group.value}`);
|
|
833
|
+
result.push(...files.map((file) => file.path));
|
|
834
|
+
}
|
|
835
|
+
(0, debug_1.debug)(`Found ${result.length} files in synchronized root groups for target: ${nativeTarget.obj.name}`);
|
|
836
|
+
return result;
|
|
837
|
+
}
|
|
838
|
+
getFilesInSynchronizedRootGroup(group) {
|
|
839
|
+
// Group path is expected to be set, therefore typing is non-nullable.
|
|
840
|
+
// As the group is loaded from a project file, it is not guaranteed to be set,
|
|
841
|
+
// therefore we treat it as optional.
|
|
842
|
+
if (!group.obj.path) {
|
|
843
|
+
(0, debug_1.debug)(`Group path not found for group: ${group.id}`);
|
|
844
|
+
return [];
|
|
845
|
+
}
|
|
846
|
+
// Resolve the path of the synchronized root group
|
|
847
|
+
const absoluteGroupPath = this.resolveAbsolutePathOfSynchronizedRootGroup(group);
|
|
848
|
+
if (!absoluteGroupPath) {
|
|
849
|
+
(0, debug_1.debug)(`Failed to resolve path of synchronized root group: ${group.id}`);
|
|
850
|
+
return [];
|
|
851
|
+
}
|
|
852
|
+
// Build a list of all exception paths for the group
|
|
853
|
+
const exceptionSets = this.getExceptionSetsForGroup(group);
|
|
854
|
+
// Resolve a list of all files in the group
|
|
855
|
+
const files = this.getAbsoluteFilePathsInDirectoryTree(absoluteGroupPath);
|
|
856
|
+
// Filter out files that are excluded by the exception sets
|
|
857
|
+
const filteredFiles = this.filterFilesByExceptionSets(files, exceptionSets);
|
|
858
|
+
return filteredFiles;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Returns all files in a directory tree.
|
|
862
|
+
*
|
|
863
|
+
* @param dirPath - The path of the directory to get the files in
|
|
864
|
+
* @returns All files in the directory tree, or an empty array if the directory does not exist
|
|
865
|
+
*/
|
|
866
|
+
getAbsoluteFilePathsInDirectoryTree(dirPath) {
|
|
867
|
+
// If the directory does not exist, return an empty array
|
|
868
|
+
// This can happen if the group is not found in the project
|
|
869
|
+
if (!fs.existsSync(dirPath)) {
|
|
870
|
+
return [];
|
|
871
|
+
}
|
|
872
|
+
const result = [];
|
|
873
|
+
const files = fs.readdirSync(dirPath);
|
|
874
|
+
for (const file of files) {
|
|
875
|
+
// Ignore hidden files and directories
|
|
876
|
+
if (file.startsWith('.')) {
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
const filePath = path.join(dirPath, file);
|
|
880
|
+
// If the file is a directory, recursively get the files in the directory
|
|
881
|
+
if (fs.statSync(filePath).isDirectory()) {
|
|
882
|
+
result.push(...this.getAbsoluteFilePathsInDirectoryTree(filePath));
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
// If the file is a file, add it to the result
|
|
886
|
+
if (fs.statSync(filePath).isFile()) {
|
|
309
887
|
result.push({
|
|
310
|
-
|
|
311
|
-
path:
|
|
888
|
+
name: file,
|
|
889
|
+
path: filePath,
|
|
312
890
|
});
|
|
313
|
-
|
|
314
|
-
else if (groupReference) {
|
|
315
|
-
if (typeof groupReference === 'string') {
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
const groupChildren = this.buildGroup(groupReference, groupReference.path
|
|
319
|
-
? `${path}${groupReference.path.replace(/"/g, '')}/`
|
|
320
|
-
: path);
|
|
321
|
-
result.push(...groupChildren);
|
|
891
|
+
continue;
|
|
322
892
|
}
|
|
323
893
|
}
|
|
324
894
|
return result;
|
|
325
895
|
}
|
|
896
|
+
filterFilesByExceptionSets(files, exceptionSets) {
|
|
897
|
+
// Iterate over all files and filter out files that are excluded by any exception sets
|
|
898
|
+
return files.filter((file) => {
|
|
899
|
+
return !exceptionSets.some((exceptionSet) => {
|
|
900
|
+
const membershipExceptions = exceptionSet.obj.membershipExceptions ?? [];
|
|
901
|
+
return membershipExceptions.some((path) => {
|
|
902
|
+
const unescapedPath = path.replace(/"/g, '');
|
|
903
|
+
return file.path.includes(unescapedPath);
|
|
904
|
+
});
|
|
905
|
+
});
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
// ================================ GROUP HELPERS ================================
|
|
909
|
+
/**
|
|
910
|
+
* Returns all groups that are PBXGroup.
|
|
911
|
+
*
|
|
912
|
+
* This is a helper method to avoid having to map and filter the groups manually.
|
|
913
|
+
*
|
|
914
|
+
* @returns All groups that are PBXGroup, excluding comments and non-object values.
|
|
915
|
+
*/
|
|
916
|
+
get groups() {
|
|
917
|
+
// Map and filter the groups to only include the groups that are PBXGroup
|
|
918
|
+
return Object.entries(this.objects.PBXGroup ?? {}).reduce((acc, [key, group]) => {
|
|
919
|
+
if (typeof group !== 'object') {
|
|
920
|
+
return acc;
|
|
921
|
+
}
|
|
922
|
+
return acc.concat([
|
|
923
|
+
{
|
|
924
|
+
id: key,
|
|
925
|
+
obj: group,
|
|
926
|
+
},
|
|
927
|
+
]);
|
|
928
|
+
}, new Array());
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Finds the parent group of a child group or file reference.
|
|
932
|
+
*
|
|
933
|
+
* @param childId - The ID of the child group or file reference
|
|
934
|
+
* @returns The parent group of the child group or file reference, or undefined if the child group or file reference is not found or has no parent group
|
|
935
|
+
*/
|
|
936
|
+
findParentGroupByChildId(childId) {
|
|
937
|
+
return this.groups.find((group) => {
|
|
938
|
+
return (group.obj.children ?? []).some((child) => {
|
|
939
|
+
return child.value === childId;
|
|
940
|
+
});
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Checks if a group is the main group of any project.
|
|
945
|
+
*
|
|
946
|
+
* @param groupId - The ID of the group to check
|
|
947
|
+
* @returns True if the group is the main group, false otherwise
|
|
948
|
+
*/
|
|
949
|
+
isMainGroup(groupId) {
|
|
950
|
+
return Object.values(this.objects.PBXProject ?? {}).some((project) => {
|
|
951
|
+
if (typeof project !== 'object') {
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
return project.mainGroup === groupId;
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
getExceptionSetsForGroup(group) {
|
|
958
|
+
const exceptions = group.obj.exceptions ?? [];
|
|
959
|
+
const exceptionSets = [];
|
|
960
|
+
for (const exception of exceptions) {
|
|
961
|
+
const exceptionSet = this.objects.PBXFileSystemSynchronizedBuildFileExceptionSet?.[exception.value];
|
|
962
|
+
if (typeof exceptionSet !== 'object') {
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
exceptionSets.push({
|
|
966
|
+
id: exception.value,
|
|
967
|
+
obj: exceptionSet,
|
|
968
|
+
comment: exception.comment,
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
return exceptionSets;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* The path to the build products directory for the project.
|
|
975
|
+
*
|
|
976
|
+
* This is cached to avoid having to read the build settings from Xcode for each call to `getBuildProductsDirectoryPath`.
|
|
977
|
+
*/
|
|
978
|
+
buildProductsDir;
|
|
979
|
+
/**
|
|
980
|
+
* Returns the path to the build products directory for the project.
|
|
981
|
+
*
|
|
982
|
+
* @returns The path to the build products directory for the project, or undefined if the path is not found
|
|
983
|
+
*/
|
|
984
|
+
getBuildProductsDirectoryPath() {
|
|
985
|
+
if (this.buildProductsDir) {
|
|
986
|
+
return this.buildProductsDir;
|
|
987
|
+
}
|
|
988
|
+
const buildSettings = macos_system_helper_1.MacOSSystemHelpers.readXcodeBuildSettings(this.xcodeprojPath);
|
|
989
|
+
if (!buildSettings) {
|
|
990
|
+
(0, debug_1.debug)(`Failed to read Xcode build settings`);
|
|
991
|
+
return undefined;
|
|
992
|
+
}
|
|
993
|
+
this.buildProductsDir =
|
|
994
|
+
buildSettings['TARGET_BUILD_DIR'] ?? buildSettings['BUILD_DIR'];
|
|
995
|
+
return this.buildProductsDir;
|
|
996
|
+
}
|
|
326
997
|
}
|
|
327
998
|
exports.XcodeProject = XcodeProject;
|
|
328
999
|
//# sourceMappingURL=xcode-manager.js.map
|