microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.13.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/ios/plistBuddy.ts

127lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as path from "path";
5import * as Q from "q";
6import * as glob from "glob";
7import * as fs from "fs";
8import * as semver from "semver";
9
10import {Node} from "../../common/node/node";
11import {ChildProcess} from "../../common/node/childProcess";
12import { ErrorHelper } from "../../common/error/errorHelper";
13import { InternalErrorCode } from "../../common/error/internalErrorCode";
14import { ReactNativeProjectHelper } from "../../common/reactNativeProjectHelper";
15
16export class PlistBuddy {
17 private static plistBuddyExecutable = "/usr/libexec/PlistBuddy";
18
19 private nodeChildProcess: ChildProcess;
20
21 constructor({
22 nodeChildProcess = new Node.ChildProcess(),
23 } = {}) {
24 this.nodeChildProcess = nodeChildProcess;
25 }
26
27 public getBundleId(iosProjectRoot: string, projectRoot: string, simulator: boolean = true, configuration: string = "Debug", productName?: string, scheme?: string): Q.Promise<string> {
28 return ReactNativeProjectHelper.getReactNativeVersion(projectRoot)
29 .then((rnVersion) => {
30 let productsFolder;
31 if (semver.gte(rnVersion, "0.59.0")) {
32 if (!scheme) {
33 // If no scheme were provided via runOptions.scheme or via runArguments then try to get scheme using the way RN CLI does.
34 scheme = this.getInferredScheme(iosProjectRoot, projectRoot, rnVersion);
35 }
36 productsFolder = path.join(iosProjectRoot, "build", scheme, "Build", "Products");
37 } else {
38 productsFolder = path.join(iosProjectRoot, "build", "Build", "Products");
39 }
40 const configurationFolder = path.join(productsFolder, `${configuration}${simulator ? "-iphonesimulator" : "-iphoneos"}`);
41 let executable = "";
42 if (productName) {
43 executable = `${productName}.app`;
44 } else {
45 const executableList = this.findExecutable(configurationFolder);
46 if (!executableList.length) {
47 throw ErrorHelper.getInternalError(InternalErrorCode.IOSCouldNotFoundExecutableInFolder, configurationFolder);
48 } else if (executableList.length > 1) {
49 throw ErrorHelper.getInternalError(InternalErrorCode.IOSFoundMoreThanOneExecutablesCleanupBuildFolder, configurationFolder);
50 }
51 executable = `${executableList[0]}`;
52 }
53
54 const infoPlistPath = path.join(configurationFolder, executable, "Info.plist");
55 return this.invokePlistBuddy("Print:CFBundleIdentifier", infoPlistPath);
56 });
57 }
58
59 public setPlistProperty(plistFile: string, property: string, value: string): Q.Promise<void> {
60 // Attempt to set the value, and if it fails due to the key not existing attempt to create the key
61 return this.invokePlistBuddy(`Set ${property} ${value}`, plistFile).fail(() =>
62 this.invokePlistBuddy(`Add ${property} string ${value}`, plistFile)
63 ).then(() => { });
64 }
65
66 public setPlistBooleanProperty(plistFile: string, property: string, value: boolean): Q.Promise<void> {
67 // Attempt to set the value, and if it fails due to the key not existing attempt to create the key
68 return this.invokePlistBuddy(`Set ${property} ${value}`, plistFile)
69 .fail(() =>
70 this.invokePlistBuddy(`Add ${property} bool ${value}`, plistFile)
71 )
72 .then(() => { });
73 }
74
75 public deletePlistProperty(plistFile: string, property: string): Q.Promise<void> {
76 return this.invokePlistBuddy(`Delete ${property}`, plistFile).then(() => { });
77 }
78
79 public readPlistProperty(plistFile: string, property: string): Q.Promise<string> {
80 return this.invokePlistBuddy(`Print ${property}`, plistFile);
81 }
82
83 public getInferredScheme(iosProjectRoot: string, projectRoot: string, rnVersion: string) {
84 // Portion of code was taken from https://github.com/react-native-community/cli/blob/master/packages/platform-ios/src/commands/runIOS/index.js
85 // and modified a little bit
86 /**
87 * Copyright (c) Facebook, Inc. and its affiliates.
88 *
89 * This source code is licensed under the MIT license found in the
90 * LICENSE file in the root directory of this source tree.
91 *
92 * @flow
93 * @format
94 */
95 let iOSCliFolderName: string;
96 if (semver.gte(rnVersion, "0.60.0")) {
97 iOSCliFolderName = "cli-platform-ios";
98 } else {
99 iOSCliFolderName = "cli";
100 }
101 const findXcodeProject = require(path.join(projectRoot, `node_modules/@react-native-community/${iOSCliFolderName}/build/commands/runIOS/findXcodeProject`)).default;
102 const xcodeProject = findXcodeProject(fs.readdirSync(iosProjectRoot));
103 if (!xcodeProject) {
104 throw new Error(
105 `Could not find Xcode project files in "${iosProjectRoot}" folder`
106 );
107 }
108
109 const inferredSchemeName = path.basename(
110 xcodeProject.name,
111 path.extname(xcodeProject.name)
112 );
113 return inferredSchemeName;
114 }
115
116 private findExecutable(folder: string): string[] {
117 return glob.sync("*.app", {
118 cwd: folder,
119 });
120 }
121
122 private invokePlistBuddy(command: string, plistFile: string): Q.Promise<string> {
123 return this.nodeChildProcess.exec(`${PlistBuddy.plistBuddyExecutable} -c '${command}' '${plistFile}'`).outcome.then((result: string) => {
124 return result.toString().trim();
125 });
126 }
127}