1082815dcSEvan Bacon"use strict";
2082815dcSEvan Bacon
3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", {
4082815dcSEvan Bacon  value: true
5082815dcSEvan Bacon});
6082815dcSEvan Baconexports.addBuildSourceFileToGroup = addBuildSourceFileToGroup;
7082815dcSEvan Baconexports.addFileToGroupAndLink = addFileToGroupAndLink;
8082815dcSEvan Baconexports.addFramework = addFramework;
9082815dcSEvan Baconexports.addResourceFileToGroup = addResourceFileToGroup;
10082815dcSEvan Baconexports.ensureGroupRecursively = ensureGroupRecursively;
11082815dcSEvan Baconexports.getApplicationNativeTarget = getApplicationNativeTarget;
12082815dcSEvan Baconexports.getBuildConfigurationForListIdAndName = getBuildConfigurationForListIdAndName;
13082815dcSEvan Baconexports.getBuildConfigurationsForListId = getBuildConfigurationsForListId;
14082815dcSEvan Baconexports.getHackyProjectName = getHackyProjectName;
15082815dcSEvan Baconexports.getPbxproj = getPbxproj;
16082815dcSEvan Baconexports.getProductName = getProductName;
17082815dcSEvan Baconexports.getProjectName = getProjectName;
18082815dcSEvan Baconexports.getProjectSection = getProjectSection;
19082815dcSEvan Baconexports.getXCConfigurationListEntries = getXCConfigurationListEntries;
20082815dcSEvan Baconexports.isBuildConfig = isBuildConfig;
21082815dcSEvan Baconexports.isNotComment = isNotComment;
22082815dcSEvan Baconexports.isNotTestHost = isNotTestHost;
23082815dcSEvan Baconexports.resolvePathOrProject = resolvePathOrProject;
24082815dcSEvan Baconexports.sanitizedName = sanitizedName;
25082815dcSEvan Baconexports.unquote = unquote;
26082815dcSEvan Baconfunction _assert() {
27082815dcSEvan Bacon  const data = _interopRequireDefault(require("assert"));
28082815dcSEvan Bacon  _assert = function () {
29082815dcSEvan Bacon    return data;
30082815dcSEvan Bacon  };
31082815dcSEvan Bacon  return data;
32082815dcSEvan Bacon}
33082815dcSEvan Baconfunction _path() {
34082815dcSEvan Bacon  const data = _interopRequireDefault(require("path"));
35082815dcSEvan Bacon  _path = function () {
36082815dcSEvan Bacon    return data;
37082815dcSEvan Bacon  };
38082815dcSEvan Bacon  return data;
39082815dcSEvan Bacon}
40082815dcSEvan Baconfunction _slugify() {
41082815dcSEvan Bacon  const data = _interopRequireDefault(require("slugify"));
42082815dcSEvan Bacon  _slugify = function () {
43082815dcSEvan Bacon    return data;
44082815dcSEvan Bacon  };
45082815dcSEvan Bacon  return data;
46082815dcSEvan Bacon}
47082815dcSEvan Baconfunction _xcode() {
48082815dcSEvan Bacon  const data = _interopRequireDefault(require("xcode"));
49082815dcSEvan Bacon  _xcode = function () {
50082815dcSEvan Bacon    return data;
51082815dcSEvan Bacon  };
52082815dcSEvan Bacon  return data;
53082815dcSEvan Bacon}
54082815dcSEvan Baconfunction _pbxFile() {
55082815dcSEvan Bacon  const data = _interopRequireDefault(require("xcode/lib/pbxFile"));
56082815dcSEvan Bacon  _pbxFile = function () {
57082815dcSEvan Bacon    return data;
58082815dcSEvan Bacon  };
59082815dcSEvan Bacon  return data;
60082815dcSEvan Bacon}
61*8a424bebSJames Idefunction _string() {
62*8a424bebSJames Ide  const data = require("./string");
63*8a424bebSJames Ide  _string = function () {
64*8a424bebSJames Ide    return data;
65*8a424bebSJames Ide  };
66*8a424bebSJames Ide  return data;
67*8a424bebSJames Ide}
68082815dcSEvan Baconfunction _warnings() {
69082815dcSEvan Bacon  const data = require("../../utils/warnings");
70082815dcSEvan Bacon  _warnings = function () {
71082815dcSEvan Bacon    return data;
72082815dcSEvan Bacon  };
73082815dcSEvan Bacon  return data;
74082815dcSEvan Bacon}
75082815dcSEvan Baconfunction Paths() {
76082815dcSEvan Bacon  const data = _interopRequireWildcard(require("../Paths"));
77082815dcSEvan Bacon  Paths = function () {
78082815dcSEvan Bacon    return data;
79082815dcSEvan Bacon  };
80082815dcSEvan Bacon  return data;
81082815dcSEvan Bacon}
82082815dcSEvan Baconfunction _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
83082815dcSEvan Baconfunction _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
84082815dcSEvan Baconfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
85082815dcSEvan Baconfunction getProjectName(projectRoot) {
86082815dcSEvan Bacon  const sourceRoot = Paths().getSourceRoot(projectRoot);
87082815dcSEvan Bacon  return _path().default.basename(sourceRoot);
88082815dcSEvan Bacon}
89082815dcSEvan Baconfunction resolvePathOrProject(projectRootOrProject) {
90082815dcSEvan Bacon  if (typeof projectRootOrProject === 'string') {
91082815dcSEvan Bacon    try {
92082815dcSEvan Bacon      return getPbxproj(projectRootOrProject);
93082815dcSEvan Bacon    } catch {
94082815dcSEvan Bacon      return null;
95082815dcSEvan Bacon    }
96082815dcSEvan Bacon  }
97082815dcSEvan Bacon  return projectRootOrProject;
98ee216927STomasz Sapeta}
99082815dcSEvan Bacon
100ee216927STomasz Sapeta// TODO: come up with a better solution for using app.json expo.name in various places
101082815dcSEvan Baconfunction sanitizedName(name) {
102082815dcSEvan Bacon  // Default to the name `app` when every safe character has been sanitized
103082815dcSEvan Bacon  return sanitizedNameForProjects(name) || sanitizedNameForProjects((0, _slugify().default)(name)) || 'app';
104082815dcSEvan Bacon}
105082815dcSEvan Baconfunction sanitizedNameForProjects(name) {
106082815dcSEvan Bacon  return name.replace(/[\W_]+/g, '').normalize('NFD').replace(/[\u0300-\u036f]/g, '');
107ee216927STomasz Sapeta}
108ee216927STomasz Sapeta
109ee216927STomasz Sapeta// TODO: it's silly and kind of fragile that we look at app config to determine
110082815dcSEvan Bacon// the ios project paths. Overall this function needs to be revamped, just a
111082815dcSEvan Bacon// placeholder for now! Make this more robust when we support applying config
112082815dcSEvan Bacon// at any time (currently it's only applied on eject).
113082815dcSEvan Baconfunction getHackyProjectName(projectRoot, config) {
114082815dcSEvan Bacon  // Attempt to get the current ios folder name (apply).
115082815dcSEvan Bacon  try {
116082815dcSEvan Bacon    return getProjectName(projectRoot);
117082815dcSEvan Bacon  } catch {
118082815dcSEvan Bacon    // If no iOS project exists then create a new one (eject).
119082815dcSEvan Bacon    const projectName = config.name;
120082815dcSEvan Bacon    (0, _assert().default)(projectName, 'Your project needs a name in app.json/app.config.js.');
121082815dcSEvan Bacon    return sanitizedName(projectName);
122082815dcSEvan Bacon  }
123082815dcSEvan Bacon}
124082815dcSEvan Baconfunction createProjectFileForGroup({
125082815dcSEvan Bacon  filepath,
126082815dcSEvan Bacon  group
127082815dcSEvan Bacon}) {
128082815dcSEvan Bacon  const file = new (_pbxFile().default)(filepath);
129082815dcSEvan Bacon  const conflictingFile = group.children.find(child => child.comment === file.basename);
130082815dcSEvan Bacon  if (conflictingFile) {
131082815dcSEvan Bacon    // This can happen when a file like the GoogleService-Info.plist needs to be added and the eject command is run twice.
132082815dcSEvan Bacon    // Not much we can do here since it might be a conflicting file.
133082815dcSEvan Bacon    return null;
134082815dcSEvan Bacon  }
135082815dcSEvan Bacon  return file;
136082815dcSEvan Bacon}
137ee216927STomasz Sapeta
138082815dcSEvan Bacon/**
139082815dcSEvan Bacon * Add a resource file (ex: `SplashScreen.storyboard`, `Images.xcassets`) to an Xcode project.
140082815dcSEvan Bacon * This is akin to creating a new code file in Xcode with `⌘+n`.
141082815dcSEvan Bacon */
142082815dcSEvan Baconfunction addResourceFileToGroup({
143082815dcSEvan Bacon  filepath,
144082815dcSEvan Bacon  groupName,
145082815dcSEvan Bacon  // Should add to `PBXBuildFile Section`
146082815dcSEvan Bacon  isBuildFile,
147082815dcSEvan Bacon  project,
148082815dcSEvan Bacon  verbose,
149082815dcSEvan Bacon  targetUuid
150082815dcSEvan Bacon}) {
151082815dcSEvan Bacon  return addFileToGroupAndLink({
152082815dcSEvan Bacon    filepath,
153082815dcSEvan Bacon    groupName,
154082815dcSEvan Bacon    project,
155082815dcSEvan Bacon    verbose,
156082815dcSEvan Bacon    targetUuid,
157082815dcSEvan Bacon    addFileToProject({
158082815dcSEvan Bacon      project,
159082815dcSEvan Bacon      file
160082815dcSEvan Bacon    }) {
161082815dcSEvan Bacon      project.addToPbxFileReferenceSection(file);
162082815dcSEvan Bacon      if (isBuildFile) {
163082815dcSEvan Bacon        project.addToPbxBuildFileSection(file);
164082815dcSEvan Bacon      }
165082815dcSEvan Bacon      project.addToPbxResourcesBuildPhase(file);
166082815dcSEvan Bacon    }
167082815dcSEvan Bacon  });
168082815dcSEvan Bacon}
169ee216927STomasz Sapeta
170082815dcSEvan Bacon/**
171082815dcSEvan Bacon * Add a build source file (ex: `AppDelegate.m`, `ViewController.swift`) to an Xcode project.
172082815dcSEvan Bacon * This is akin to creating a new code file in Xcode with `⌘+n`.
173082815dcSEvan Bacon */
174082815dcSEvan Baconfunction addBuildSourceFileToGroup({
175082815dcSEvan Bacon  filepath,
176082815dcSEvan Bacon  groupName,
177082815dcSEvan Bacon  project,
178082815dcSEvan Bacon  verbose,
179082815dcSEvan Bacon  targetUuid
180082815dcSEvan Bacon}) {
181082815dcSEvan Bacon  return addFileToGroupAndLink({
182082815dcSEvan Bacon    filepath,
183082815dcSEvan Bacon    groupName,
184082815dcSEvan Bacon    project,
185082815dcSEvan Bacon    verbose,
186082815dcSEvan Bacon    targetUuid,
187082815dcSEvan Bacon    addFileToProject({
188082815dcSEvan Bacon      project,
189082815dcSEvan Bacon      file
190082815dcSEvan Bacon    }) {
191082815dcSEvan Bacon      project.addToPbxFileReferenceSection(file);
192082815dcSEvan Bacon      project.addToPbxBuildFileSection(file);
193082815dcSEvan Bacon      project.addToPbxSourcesBuildPhase(file);
194082815dcSEvan Bacon    }
195082815dcSEvan Bacon  });
196ee216927STomasz Sapeta}
197ee216927STomasz Sapeta
198ee216927STomasz Sapeta// TODO(brentvatne): I couldn't figure out how to do this with an existing
199082815dcSEvan Bacon// higher level function exposed by the xcode library, but we should find out how to do
200082815dcSEvan Bacon// that and replace this with it
201082815dcSEvan Baconfunction addFileToGroupAndLink({
202082815dcSEvan Bacon  filepath,
203082815dcSEvan Bacon  groupName,
204082815dcSEvan Bacon  project,
205082815dcSEvan Bacon  verbose,
206082815dcSEvan Bacon  addFileToProject,
207082815dcSEvan Bacon  targetUuid
208082815dcSEvan Bacon}) {
209082815dcSEvan Bacon  const group = pbxGroupByPathOrAssert(project, groupName);
210082815dcSEvan Bacon  const file = createProjectFileForGroup({
211082815dcSEvan Bacon    filepath,
212082815dcSEvan Bacon    group
213082815dcSEvan Bacon  });
214082815dcSEvan Bacon  if (!file) {
215082815dcSEvan Bacon    if (verbose) {
216082815dcSEvan Bacon      // This can happen when a file like the GoogleService-Info.plist needs to be added and the eject command is run twice.
217082815dcSEvan Bacon      // Not much we can do here since it might be a conflicting file.
218082815dcSEvan Bacon      (0, _warnings().addWarningIOS)('ios-xcode-project', `Skipped adding duplicate file "${filepath}" to PBXGroup named "${groupName}"`);
219082815dcSEvan Bacon    }
220082815dcSEvan Bacon    return project;
221082815dcSEvan Bacon  }
222082815dcSEvan Bacon  if (targetUuid != null) {
223082815dcSEvan Bacon    file.target = targetUuid;
224082815dcSEvan Bacon  } else {
225082815dcSEvan Bacon    const applicationNativeTarget = project.getTarget('com.apple.product-type.application');
226082815dcSEvan Bacon    file.target = applicationNativeTarget === null || applicationNativeTarget === void 0 ? void 0 : applicationNativeTarget.uuid;
227082815dcSEvan Bacon  }
228082815dcSEvan Bacon  file.uuid = project.generateUuid();
229082815dcSEvan Bacon  file.fileRef = project.generateUuid();
230082815dcSEvan Bacon  addFileToProject({
231082815dcSEvan Bacon    project,
232082815dcSEvan Bacon    file
233082815dcSEvan Bacon  });
234082815dcSEvan Bacon  group.children.push({
235082815dcSEvan Bacon    value: file.fileRef,
236082815dcSEvan Bacon    comment: file.basename
237082815dcSEvan Bacon  });
238082815dcSEvan Bacon  return project;
239082815dcSEvan Bacon}
240082815dcSEvan Baconfunction getApplicationNativeTarget({
241082815dcSEvan Bacon  project,
242082815dcSEvan Bacon  projectName
243082815dcSEvan Bacon}) {
244082815dcSEvan Bacon  const applicationNativeTarget = project.getTarget('com.apple.product-type.application');
245082815dcSEvan Bacon  (0, _assert().default)(applicationNativeTarget, `Couldn't locate application PBXNativeTarget in '.xcodeproj' file.`);
246082815dcSEvan Bacon  (0, _assert().default)(String(applicationNativeTarget.target.name) === projectName, `Application native target name mismatch. Expected ${projectName}, but found ${applicationNativeTarget.target.name}.`);
247082815dcSEvan Bacon  return applicationNativeTarget;
248082815dcSEvan Bacon}
249ee216927STomasz Sapeta
250082815dcSEvan Bacon/**
251082815dcSEvan Bacon * Add a framework to the default app native target.
252082815dcSEvan Bacon *
253082815dcSEvan Bacon * @param projectName Name of the PBX project.
254082815dcSEvan Bacon * @param framework String ending in `.framework`, i.e. `StoreKit.framework`
255082815dcSEvan Bacon */
256082815dcSEvan Baconfunction addFramework({
257082815dcSEvan Bacon  project,
258082815dcSEvan Bacon  projectName,
259082815dcSEvan Bacon  framework
260082815dcSEvan Bacon}) {
261082815dcSEvan Bacon  const target = getApplicationNativeTarget({
262082815dcSEvan Bacon    project,
263082815dcSEvan Bacon    projectName
264082815dcSEvan Bacon  });
265082815dcSEvan Bacon  return project.addFramework(framework, {
266082815dcSEvan Bacon    target: target.uuid
267082815dcSEvan Bacon  });
268082815dcSEvan Bacon}
269082815dcSEvan Baconfunction splitPath(path) {
270082815dcSEvan Bacon  // TODO: Should we account for other platforms that may not use `/`
271082815dcSEvan Bacon  return path.split('/');
272082815dcSEvan Bacon}
273082815dcSEvan Baconconst findGroup = (group, name) => {
274082815dcSEvan Bacon  if (!group) {
275082815dcSEvan Bacon    return undefined;
276082815dcSEvan Bacon  }
277082815dcSEvan Bacon  return group.children.find(group => group.comment === name);
278082815dcSEvan Bacon};
279082815dcSEvan Baconfunction findGroupInsideGroup(project, group, name) {
280082815dcSEvan Bacon  const foundGroup = findGroup(group, name);
281082815dcSEvan Bacon  if (foundGroup) {
282082815dcSEvan Bacon    var _project$getPBXGroupB;
283082815dcSEvan Bacon    return (_project$getPBXGroupB = project.getPBXGroupByKey(foundGroup.value)) !== null && _project$getPBXGroupB !== void 0 ? _project$getPBXGroupB : null;
284082815dcSEvan Bacon  }
285082815dcSEvan Bacon  return null;
286082815dcSEvan Bacon}
287082815dcSEvan Baconfunction pbxGroupByPathOrAssert(project, path) {
288082815dcSEvan Bacon  const {
289082815dcSEvan Bacon    firstProject
290082815dcSEvan Bacon  } = project.getFirstProject();
291082815dcSEvan Bacon  let group = project.getPBXGroupByKey(firstProject.mainGroup);
292082815dcSEvan Bacon  const components = splitPath(path);
293082815dcSEvan Bacon  for (const name of components) {
294082815dcSEvan Bacon    const nextGroup = findGroupInsideGroup(project, group, name);
295082815dcSEvan Bacon    if (nextGroup) {
296082815dcSEvan Bacon      group = nextGroup;
297082815dcSEvan Bacon    } else {
298082815dcSEvan Bacon      break;
299082815dcSEvan Bacon    }
300082815dcSEvan Bacon  }
301082815dcSEvan Bacon  if (!group) {
302082815dcSEvan Bacon    throw Error(`Xcode PBXGroup with name "${path}" could not be found in the Xcode project.`);
303082815dcSEvan Bacon  }
304082815dcSEvan Bacon  return group;
305082815dcSEvan Bacon}
306082815dcSEvan Baconfunction ensureGroupRecursively(project, filepath) {
307082815dcSEvan Bacon  var _topMostGroup;
308082815dcSEvan Bacon  const components = splitPath(filepath);
309082815dcSEvan Bacon  const hasChild = (group, name) => group.children.find(({
310082815dcSEvan Bacon    comment
311082815dcSEvan Bacon  }) => comment === name);
312082815dcSEvan Bacon  const {
313082815dcSEvan Bacon    firstProject
314082815dcSEvan Bacon  } = project.getFirstProject();
315082815dcSEvan Bacon  let topMostGroup = project.getPBXGroupByKey(firstProject.mainGroup);
316082815dcSEvan Bacon  for (const pathComponent of components) {
317082815dcSEvan Bacon    if (topMostGroup && !hasChild(topMostGroup, pathComponent)) {
318082815dcSEvan Bacon      topMostGroup.children.push({
319082815dcSEvan Bacon        comment: pathComponent,
320082815dcSEvan Bacon        value: project.pbxCreateGroup(pathComponent, '""')
321082815dcSEvan Bacon      });
322082815dcSEvan Bacon    }
323082815dcSEvan Bacon    topMostGroup = project.pbxGroupByName(pathComponent);
324082815dcSEvan Bacon  }
325082815dcSEvan Bacon  return (_topMostGroup = topMostGroup) !== null && _topMostGroup !== void 0 ? _topMostGroup : null;
326082815dcSEvan Bacon}
327ee216927STomasz Sapeta
328082815dcSEvan Bacon/**
329082815dcSEvan Bacon * Get the pbxproj for the given path
330082815dcSEvan Bacon */
331082815dcSEvan Baconfunction getPbxproj(projectRoot) {
332082815dcSEvan Bacon  const projectPath = Paths().getPBXProjectPath(projectRoot);
333082815dcSEvan Bacon  const project = _xcode().default.project(projectPath);
334082815dcSEvan Bacon  project.parseSync();
335082815dcSEvan Bacon  return project;
336082815dcSEvan Bacon}
337ee216927STomasz Sapeta
338082815dcSEvan Bacon/**
339082815dcSEvan Bacon * Get the productName for a project, if the name is using a variable `$(TARGET_NAME)`, then attempt to get the value of that variable.
340082815dcSEvan Bacon *
341082815dcSEvan Bacon * @param project
342082815dcSEvan Bacon */
343082815dcSEvan Baconfunction getProductName(project) {
344082815dcSEvan Bacon  let productName = '$(TARGET_NAME)';
345082815dcSEvan Bacon  try {
346082815dcSEvan Bacon    // If the product name is numeric, this will fail (it's a getter).
347082815dcSEvan Bacon    // If the bundle identifier' final component is only numeric values, then the PRODUCT_NAME
348082815dcSEvan Bacon    // will be a numeric value, this results in a bug where the product name isn't useful,
349082815dcSEvan Bacon    // i.e. `com.bacon.001` -> `1` -- in this case, use the first target name.
350082815dcSEvan Bacon    productName = project.productName;
351082815dcSEvan Bacon  } catch {}
352082815dcSEvan Bacon  if (productName === '$(TARGET_NAME)') {
353082815dcSEvan Bacon    var _project$getFirstTarg, _project$getFirstTarg2;
354082815dcSEvan Bacon    const targetName = (_project$getFirstTarg = project.getFirstTarget()) === null || _project$getFirstTarg === void 0 ? void 0 : (_project$getFirstTarg2 = _project$getFirstTarg.firstTarget) === null || _project$getFirstTarg2 === void 0 ? void 0 : _project$getFirstTarg2.productName;
355082815dcSEvan Bacon    productName = targetName !== null && targetName !== void 0 ? targetName : productName;
356082815dcSEvan Bacon  }
357082815dcSEvan Bacon  return productName;
358082815dcSEvan Bacon}
359082815dcSEvan Baconfunction getProjectSection(project) {
360082815dcSEvan Bacon  return project.pbxProjectSection();
361082815dcSEvan Bacon}
362082815dcSEvan Baconfunction getXCConfigurationListEntries(project) {
363082815dcSEvan Bacon  const lists = project.pbxXCConfigurationList();
364082815dcSEvan Bacon  return Object.entries(lists).filter(isNotComment);
365082815dcSEvan Bacon}
366082815dcSEvan Baconfunction getBuildConfigurationsForListId(project, configurationListId) {
367082815dcSEvan Bacon  const configurationListEntries = getXCConfigurationListEntries(project);
368082815dcSEvan Bacon  const [, configurationList] = configurationListEntries.find(([key]) => key === configurationListId);
369082815dcSEvan Bacon  const buildConfigurations = configurationList.buildConfigurations.map(i => i.value);
370082815dcSEvan Bacon  return Object.entries(project.pbxXCBuildConfigurationSection()).filter(isNotComment).filter(isBuildConfig).filter(([key]) => buildConfigurations.includes(key));
371082815dcSEvan Bacon}
372082815dcSEvan Baconfunction getBuildConfigurationForListIdAndName(project, {
373082815dcSEvan Bacon  configurationListId,
374082815dcSEvan Bacon  buildConfiguration
375082815dcSEvan Bacon}) {
376082815dcSEvan Bacon  const xcBuildConfigurationEntry = getBuildConfigurationsForListId(project, configurationListId).find(i => (0, _string().trimQuotes)(i[1].name) === buildConfiguration);
377082815dcSEvan Bacon  if (!xcBuildConfigurationEntry) {
378082815dcSEvan Bacon    throw new Error(`Build configuration '${buildConfiguration}' does not exist in list with id '${configurationListId}'`);
379082815dcSEvan Bacon  }
380082815dcSEvan Bacon  return xcBuildConfigurationEntry;
381082815dcSEvan Bacon}
382082815dcSEvan Baconfunction isBuildConfig([, sectionItem]) {
383082815dcSEvan Bacon  return sectionItem.isa === 'XCBuildConfiguration';
384082815dcSEvan Bacon}
385082815dcSEvan Baconfunction isNotTestHost([, sectionItem]) {
386082815dcSEvan Bacon  return !sectionItem.buildSettings.TEST_HOST;
387082815dcSEvan Bacon}
388082815dcSEvan Baconfunction isNotComment([key]) {
389082815dcSEvan Bacon  return !key.endsWith(`_comment`);
390ee216927STomasz Sapeta}
391082815dcSEvan Bacon
392ee216927STomasz Sapeta// Remove surrounding double quotes if they exist.
393082815dcSEvan Baconfunction unquote(value) {
394082815dcSEvan Bacon  var _value$match$, _value$match;
395082815dcSEvan Bacon  // projects with numeric names will fail due to a bug in the xcode package.
396082815dcSEvan Bacon  if (typeof value === 'number') {
397082815dcSEvan Bacon    value = String(value);
398082815dcSEvan Bacon  }
399082815dcSEvan Bacon  return (_value$match$ = (_value$match = value.match(/^"(.*)"$/)) === null || _value$match === void 0 ? void 0 : _value$match[1]) !== null && _value$match$ !== void 0 ? _value$match$ : value;
400082815dcSEvan Bacon}
401082815dcSEvan Bacon//# sourceMappingURL=Xcodeproj.js.map