microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.11.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/ios/plistBuddy.ts

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