@bravemobile/react-native-code-push 13.1.0-beta.5 → 13.1.0-beta.6

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.
@@ -0,0 +1,118 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
5
+ import { buildPatchTools, hashBuildScript } from "./buildPatchTools.js";
6
+
7
+ /**
8
+ * The command is a thin wrapper around the build script this package ships. What it has
9
+ * to get right is what it hands the script: the directory the CLI will later look in, and
10
+ * `--force` when asked. A script that records what it was handed proves both without
11
+ * cloning and compiling HDiffPatch. The shipped script is run once at the end, against an
12
+ * install it already finds complete, to show the wrapper speaks its actual interface.
13
+ */
14
+
15
+ const REPO_ROOT = path.resolve(__dirname, "..", "..", "..");
16
+ const SHIPPED_BUILD_SCRIPT = path.join(REPO_ROOT, "scripts", "binary-patch", "build-hdiffpatch.sh");
17
+ /** Where `jest.globalSetup.ts` built the tools for this run. */
18
+ const INSTALLED_TOOLS_DIR = process.env.HDIFFPATCH_TOOLS_DIR || path.join(REPO_ROOT, ".hdiffpatch-tools");
19
+
20
+ let workDir: string;
21
+
22
+ beforeEach(() => {
23
+ workDir = fs.mkdtempSync(path.join(os.tmpdir(), "build-patch-tools-"));
24
+ });
25
+
26
+ afterEach(() => {
27
+ fs.rmSync(workDir, { recursive: true, force: true });
28
+ });
29
+
30
+ function writeScript(body: string): string {
31
+ const scriptPath = path.join(workDir, "build.sh");
32
+ fs.writeFileSync(scriptPath, `#!/bin/sh\n${body}\n`, { mode: 0o755 });
33
+ return scriptPath;
34
+ }
35
+
36
+ /** A script that writes the install directory it was given, then each argument, one per line. */
37
+ function writeRecordingScript(): string {
38
+ return writeScript('printf \'%s\\n\' "$HDIFFPATCH_TOOLS_DIR" "$@" > "$HDIFFPATCH_TOOLS_DIR/invocation"');
39
+ }
40
+
41
+ function readInvocation(toolsDir: string): string[] {
42
+ return fs.readFileSync(path.join(toolsDir, "invocation"), "utf8").trimEnd().split("\n");
43
+ }
44
+
45
+ describe("buildPatchTools", () => {
46
+ it("runs the build script against the tools directory it was given, without forcing a rebuild", () => {
47
+ const toolsDir = path.join(workDir, "tools");
48
+ fs.mkdirSync(toolsDir);
49
+
50
+ buildPatchTools({ buildScriptPath: writeRecordingScript(), toolsDir, force: false });
51
+
52
+ expect(readInvocation(toolsDir)).toEqual([toolsDir]);
53
+ });
54
+
55
+ it("asks the build script to rebuild when forced", () => {
56
+ const toolsDir = path.join(workDir, "tools");
57
+ fs.mkdirSync(toolsDir);
58
+
59
+ buildPatchTools({ buildScriptPath: writeRecordingScript(), toolsDir, force: true });
60
+
61
+ expect(readInvocation(toolsDir)).toEqual([toolsDir, "--force"]);
62
+ });
63
+
64
+ it("fails with the exit code when the build script fails", () => {
65
+ const buildScriptPath = writeScript("exit 3");
66
+
67
+ expect(() => buildPatchTools({ buildScriptPath, toolsDir: workDir, force: false })).toThrow(/exit code 3/);
68
+ });
69
+
70
+ it("fails naming the script when it cannot be started", () => {
71
+ const buildScriptPath = path.join(workDir, "no-such-script.sh");
72
+
73
+ expect(() => buildPatchTools({ buildScriptPath, toolsDir: workDir, force: false })).toThrow(
74
+ /no-such-script\.sh/,
75
+ );
76
+ });
77
+
78
+ it("succeeds against an install the shipped script already finds complete", () => {
79
+ // Without an install the shipped script clones and compiles for minutes, and
80
+ // `spawnSync` holds the worker past any jest timeout. `jest.globalSetup.ts`
81
+ // provides the install; this says so when it did not.
82
+ const missing = ["hdiffz", "hpatchz"].filter((tool) => !fs.existsSync(path.join(INSTALLED_TOOLS_DIR, tool)));
83
+ if (missing.length > 0) {
84
+ throw new Error(
85
+ `${missing.join(", ")} not installed in ${INSTALLED_TOOLS_DIR}: jest.globalSetup.ts should have built the tools first`,
86
+ );
87
+ }
88
+
89
+ expect(() =>
90
+ buildPatchTools({ buildScriptPath: SHIPPED_BUILD_SCRIPT, toolsDir: INSTALLED_TOOLS_DIR, force: false }),
91
+ ).not.toThrow();
92
+ });
93
+ });
94
+
95
+ /**
96
+ * A CI cache of the installed tools is keyed by this hash, so it has to stay the same for as
97
+ * long as the script would build the same tools, and change as soon as it would not.
98
+ */
99
+ describe("hashBuildScript", () => {
100
+ it("hashes two scripts with the same contents to the same hex digest", () => {
101
+ const first = path.join(workDir, "first.sh");
102
+ const second = path.join(workDir, "second.sh");
103
+ fs.writeFileSync(first, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
104
+ fs.writeFileSync(second, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
105
+
106
+ expect(hashBuildScript(first)).toBe(hashBuildScript(second));
107
+ expect(hashBuildScript(first)).toMatch(/^[0-9a-f]{64}$/);
108
+ });
109
+
110
+ it("hashes a script whose pinned version changed to a different value", () => {
111
+ const before = path.join(workDir, "before.sh");
112
+ const after = path.join(workDir, "after.sh");
113
+ fs.writeFileSync(before, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
114
+ fs.writeFileSync(after, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.4\n");
115
+
116
+ expect(hashBuildScript(after)).not.toBe(hashBuildScript(before));
117
+ });
118
+ });
@@ -0,0 +1,46 @@
1
+ import { spawnSync } from "child_process";
2
+ import crypto from "crypto";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { TOOLS_DIR_ENV_NAME } from "../../utils/binaryPatch.js";
6
+
7
+ interface BuildPatchToolsOptions {
8
+ /** The `build-hdiffpatch.sh` this package ships. */
9
+ buildScriptPath: string;
10
+ /** Where the script installs `hdiffz` and `hpatchz`. It has to be a place the CLI looks in. */
11
+ toolsDir: string;
12
+ /** Rebuild even when both tools are already there. */
13
+ force: boolean;
14
+ }
15
+
16
+ /**
17
+ * Runs the build script with the install directory the caller chose.
18
+ *
19
+ * The script's output goes straight to the terminal: a first build clones and compiles
20
+ * HDiffPatch, which takes minutes, and a silent wait would look like a hang. So when the
21
+ * script fails, its own message has already been shown, and the error raised here only
22
+ * has to say that it did.
23
+ */
24
+ export function buildPatchTools({ buildScriptPath, toolsDir, force }: BuildPatchToolsOptions): void {
25
+ const result = spawnSync(buildScriptPath, force ? ['--force'] : [], {
26
+ stdio: 'inherit',
27
+ env: { ...process.env, [TOOLS_DIR_ENV_NAME]: toolsDir },
28
+ });
29
+
30
+ if (result.error) {
31
+ throw new Error(`failed to run ${buildScriptPath}: ${result.error.message}`);
32
+ }
33
+ if (result.status !== 0) {
34
+ const reason = result.status === null ? `signal ${result.signal}` : `exit code ${result.status}`;
35
+ throw new Error(`${path.basename(buildScriptPath)} failed with ${reason}`);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * SHA-256 of the build script's bytes, for keying a CI cache of the installed tools. The
41
+ * script pins the sources and the build flags, so it changes whenever the tools it would
42
+ * build do.
43
+ */
44
+ export function hashBuildScript(buildScriptPath: string): string {
45
+ return crypto.createHash('sha256').update(fs.readFileSync(buildScriptPath)).digest('hex');
46
+ }
@@ -0,0 +1,44 @@
1
+ import path from "path";
2
+ import { fileURLToPath } from "url";
3
+ import { program } from "commander";
4
+ import { TOOLS_DIR_ENV_NAME, TOOLS_DIR_NAME } from "../../utils/binaryPatch.js";
5
+ import { buildPatchTools, hashBuildScript } from "./buildPatchTools.js";
6
+
7
+ type Options = {
8
+ toolsDir: string;
9
+ force: boolean;
10
+ printHash: boolean;
11
+ }
12
+
13
+ /**
14
+ * The CLI runs compiled, from `cli/dist/commands/buildPatchToolsCommand/`, which puts the
15
+ * package root - and the script shipped under it - four levels up.
16
+ */
17
+ const BUILD_SCRIPT_PATH = fileURLToPath(
18
+ new URL("../../../../scripts/binary-patch/build-hdiffpatch.sh", import.meta.url),
19
+ );
20
+
21
+ /**
22
+ * Installs where `release` will look: `HDIFFPATCH_TOOLS_DIR` when it is set, and otherwise
23
+ * a `.hdiffpatch-tools` directory in the working directory, the first place the lookup
24
+ * checks before walking up.
25
+ */
26
+ const DEFAULT_TOOLS_DIR = process.env[TOOLS_DIR_ENV_NAME] || path.resolve(process.cwd(), TOOLS_DIR_NAME);
27
+
28
+ program.command('build-patch-tools')
29
+ .description('Builds hdiffz and hpatchz from source and installs them where `release --binary-bundle-path` looks for them.\nThe build clones the pinned HDiffPatch sources, so it needs git, make, a C/C++ compiler and network access. It does nothing when the tools are already installed.')
30
+ .option('--tools-dir <path>', 'directory to install the tools into', DEFAULT_TOOLS_DIR)
31
+ .option('--force', 'rebuild even when the tools are already installed', false)
32
+ .option('--print-hash', 'print a hash of the build script, for keying a CI cache of the tools, and exit without building', false)
33
+ .action((options: Options) => {
34
+ if (options.printHash) {
35
+ console.log(hashBuildScript(BUILD_SCRIPT_PATH));
36
+ return;
37
+ }
38
+
39
+ buildPatchTools({
40
+ buildScriptPath: BUILD_SCRIPT_PATH,
41
+ toolsDir: path.resolve(options.toolsDir),
42
+ force: options.force,
43
+ });
44
+ });
@@ -0,0 +1,34 @@
1
+ import { spawnSync } from "child_process";
2
+ import crypto from "crypto";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { TOOLS_DIR_ENV_NAME } from "../../utils/binaryPatch.js";
6
+ /**
7
+ * Runs the build script with the install directory the caller chose.
8
+ *
9
+ * The script's output goes straight to the terminal: a first build clones and compiles
10
+ * HDiffPatch, which takes minutes, and a silent wait would look like a hang. So when the
11
+ * script fails, its own message has already been shown, and the error raised here only
12
+ * has to say that it did.
13
+ */
14
+ export function buildPatchTools({ buildScriptPath, toolsDir, force }) {
15
+ const result = spawnSync(buildScriptPath, force ? ['--force'] : [], {
16
+ stdio: 'inherit',
17
+ env: { ...process.env, [TOOLS_DIR_ENV_NAME]: toolsDir },
18
+ });
19
+ if (result.error) {
20
+ throw new Error(`failed to run ${buildScriptPath}: ${result.error.message}`);
21
+ }
22
+ if (result.status !== 0) {
23
+ const reason = result.status === null ? `signal ${result.signal}` : `exit code ${result.status}`;
24
+ throw new Error(`${path.basename(buildScriptPath)} failed with ${reason}`);
25
+ }
26
+ }
27
+ /**
28
+ * SHA-256 of the build script's bytes, for keying a CI cache of the installed tools. The
29
+ * script pins the sources and the build flags, so it changes whenever the tools it would
30
+ * build do.
31
+ */
32
+ export function hashBuildScript(buildScriptPath) {
33
+ return crypto.createHash('sha256').update(fs.readFileSync(buildScriptPath)).digest('hex');
34
+ }
@@ -0,0 +1,88 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
5
+ import { buildPatchTools, hashBuildScript } from "./buildPatchTools.js";
6
+ /**
7
+ * The command is a thin wrapper around the build script this package ships. What it has
8
+ * to get right is what it hands the script: the directory the CLI will later look in, and
9
+ * `--force` when asked. A script that records what it was handed proves both without
10
+ * cloning and compiling HDiffPatch. The shipped script is run once at the end, against an
11
+ * install it already finds complete, to show the wrapper speaks its actual interface.
12
+ */
13
+ const REPO_ROOT = path.resolve(__dirname, "..", "..", "..");
14
+ const SHIPPED_BUILD_SCRIPT = path.join(REPO_ROOT, "scripts", "binary-patch", "build-hdiffpatch.sh");
15
+ /** Where `jest.globalSetup.ts` built the tools for this run. */
16
+ const INSTALLED_TOOLS_DIR = process.env.HDIFFPATCH_TOOLS_DIR || path.join(REPO_ROOT, ".hdiffpatch-tools");
17
+ let workDir;
18
+ beforeEach(() => {
19
+ workDir = fs.mkdtempSync(path.join(os.tmpdir(), "build-patch-tools-"));
20
+ });
21
+ afterEach(() => {
22
+ fs.rmSync(workDir, { recursive: true, force: true });
23
+ });
24
+ function writeScript(body) {
25
+ const scriptPath = path.join(workDir, "build.sh");
26
+ fs.writeFileSync(scriptPath, `#!/bin/sh\n${body}\n`, { mode: 0o755 });
27
+ return scriptPath;
28
+ }
29
+ /** A script that writes the install directory it was given, then each argument, one per line. */
30
+ function writeRecordingScript() {
31
+ return writeScript('printf \'%s\\n\' "$HDIFFPATCH_TOOLS_DIR" "$@" > "$HDIFFPATCH_TOOLS_DIR/invocation"');
32
+ }
33
+ function readInvocation(toolsDir) {
34
+ return fs.readFileSync(path.join(toolsDir, "invocation"), "utf8").trimEnd().split("\n");
35
+ }
36
+ describe("buildPatchTools", () => {
37
+ it("runs the build script against the tools directory it was given, without forcing a rebuild", () => {
38
+ const toolsDir = path.join(workDir, "tools");
39
+ fs.mkdirSync(toolsDir);
40
+ buildPatchTools({ buildScriptPath: writeRecordingScript(), toolsDir, force: false });
41
+ expect(readInvocation(toolsDir)).toEqual([toolsDir]);
42
+ });
43
+ it("asks the build script to rebuild when forced", () => {
44
+ const toolsDir = path.join(workDir, "tools");
45
+ fs.mkdirSync(toolsDir);
46
+ buildPatchTools({ buildScriptPath: writeRecordingScript(), toolsDir, force: true });
47
+ expect(readInvocation(toolsDir)).toEqual([toolsDir, "--force"]);
48
+ });
49
+ it("fails with the exit code when the build script fails", () => {
50
+ const buildScriptPath = writeScript("exit 3");
51
+ expect(() => buildPatchTools({ buildScriptPath, toolsDir: workDir, force: false })).toThrow(/exit code 3/);
52
+ });
53
+ it("fails naming the script when it cannot be started", () => {
54
+ const buildScriptPath = path.join(workDir, "no-such-script.sh");
55
+ expect(() => buildPatchTools({ buildScriptPath, toolsDir: workDir, force: false })).toThrow(/no-such-script\.sh/);
56
+ });
57
+ it("succeeds against an install the shipped script already finds complete", () => {
58
+ // Without an install the shipped script clones and compiles for minutes, and
59
+ // `spawnSync` holds the worker past any jest timeout. `jest.globalSetup.ts`
60
+ // provides the install; this says so when it did not.
61
+ const missing = ["hdiffz", "hpatchz"].filter((tool) => !fs.existsSync(path.join(INSTALLED_TOOLS_DIR, tool)));
62
+ if (missing.length > 0) {
63
+ throw new Error(`${missing.join(", ")} not installed in ${INSTALLED_TOOLS_DIR}: jest.globalSetup.ts should have built the tools first`);
64
+ }
65
+ expect(() => buildPatchTools({ buildScriptPath: SHIPPED_BUILD_SCRIPT, toolsDir: INSTALLED_TOOLS_DIR, force: false })).not.toThrow();
66
+ });
67
+ });
68
+ /**
69
+ * A CI cache of the installed tools is keyed by this hash, so it has to stay the same for as
70
+ * long as the script would build the same tools, and change as soon as it would not.
71
+ */
72
+ describe("hashBuildScript", () => {
73
+ it("hashes two scripts with the same contents to the same hex digest", () => {
74
+ const first = path.join(workDir, "first.sh");
75
+ const second = path.join(workDir, "second.sh");
76
+ fs.writeFileSync(first, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
77
+ fs.writeFileSync(second, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
78
+ expect(hashBuildScript(first)).toBe(hashBuildScript(second));
79
+ expect(hashBuildScript(first)).toMatch(/^[0-9a-f]{64}$/);
80
+ });
81
+ it("hashes a script whose pinned version changed to a different value", () => {
82
+ const before = path.join(workDir, "before.sh");
83
+ const after = path.join(workDir, "after.sh");
84
+ fs.writeFileSync(before, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.3\n");
85
+ fs.writeFileSync(after, "#!/bin/sh\nHDIFFPATCH_TAG=v5.1.4\n");
86
+ expect(hashBuildScript(after)).not.toBe(hashBuildScript(before));
87
+ });
88
+ });
@@ -0,0 +1,32 @@
1
+ import path from "path";
2
+ import { fileURLToPath } from "url";
3
+ import { program } from "commander";
4
+ import { TOOLS_DIR_ENV_NAME, TOOLS_DIR_NAME } from "../../utils/binaryPatch.js";
5
+ import { buildPatchTools, hashBuildScript } from "./buildPatchTools.js";
6
+ /**
7
+ * The CLI runs compiled, from `cli/dist/commands/buildPatchToolsCommand/`, which puts the
8
+ * package root - and the script shipped under it - four levels up.
9
+ */
10
+ const BUILD_SCRIPT_PATH = fileURLToPath(new URL("../../../../scripts/binary-patch/build-hdiffpatch.sh", import.meta.url));
11
+ /**
12
+ * Installs where `release` will look: `HDIFFPATCH_TOOLS_DIR` when it is set, and otherwise
13
+ * a `.hdiffpatch-tools` directory in the working directory, the first place the lookup
14
+ * checks before walking up.
15
+ */
16
+ const DEFAULT_TOOLS_DIR = process.env[TOOLS_DIR_ENV_NAME] || path.resolve(process.cwd(), TOOLS_DIR_NAME);
17
+ program.command('build-patch-tools')
18
+ .description('Builds hdiffz and hpatchz from source and installs them where `release --binary-bundle-path` looks for them.\nThe build clones the pinned HDiffPatch sources, so it needs git, make, a C/C++ compiler and network access. It does nothing when the tools are already installed.')
19
+ .option('--tools-dir <path>', 'directory to install the tools into', DEFAULT_TOOLS_DIR)
20
+ .option('--force', 'rebuild even when the tools are already installed', false)
21
+ .option('--print-hash', 'print a hash of the build script, for keying a CI cache of the tools, and exit without building', false)
22
+ .action((options) => {
23
+ if (options.printHash) {
24
+ console.log(hashBuildScript(BUILD_SCRIPT_PATH));
25
+ return;
26
+ }
27
+ buildPatchTools({
28
+ buildScriptPath: BUILD_SCRIPT_PATH,
29
+ toolsDir: path.resolve(options.toolsDir),
30
+ force: options.force,
31
+ });
32
+ });
package/cli/dist/index.js CHANGED
@@ -26,6 +26,10 @@ import "./commands/showHistoryCommand/index.js";
26
26
  * npx code-push init
27
27
  */
28
28
  import "./commands/initCommand/index.js";
29
+ /**
30
+ * npx code-push build-patch-tools
31
+ */
32
+ import "./commands/buildPatchToolsCommand/index.js";
29
33
  shell.set("-e");
30
34
  shell.set("+v");
31
35
  program
@@ -31,14 +31,17 @@ export const BINARY_PATCH_ALGORITHM = 'hdiffpatch-m-zstd';
31
31
  export const BINARY_PATCH_FORMAT_VERSION = 1;
32
32
  const HDIFFZ_OPTIONS = ['-f', '-m-6', '-c-zstd-21-24'];
33
33
  const HPATCHZ_OPTIONS = ['-f', '-m'];
34
- const TOOLS_DIR_ENV_NAME = 'HDIFFPATCH_TOOLS_DIR';
35
- const TOOLS_DIR_NAME = '.hdiffpatch-tools';
36
- const BUILD_SCRIPT_PATH = 'scripts/binary-patch/build-hdiffpatch.sh';
34
+ export const TOOLS_DIR_ENV_NAME = 'HDIFFPATCH_TOOLS_DIR';
35
+ export const TOOLS_DIR_NAME = '.hdiffpatch-tools';
36
+ const BUILD_COMMAND = 'npx code-push build-patch-tools';
37
37
  /**
38
38
  * Finds the hdiffz/hpatchz executable, looking at `HDIFFPATCH_TOOLS_DIR` first and
39
39
  * then at a `.hdiffpatch-tools` directory in the working directory or any directory
40
40
  * above it. The tools are built from source rather than installed as a package
41
41
  * dependency, so the error explains how to get them.
42
+ *
43
+ * `build-patch-tools` (`cli/commands/buildPatchToolsCommand/index.ts`) installs into the
44
+ * first place this looks; a change to the lookup order has to be mirrored there.
42
45
  */
43
46
  export function resolveBinaryPatchTool(tool) {
44
47
  const configuredDir = process.env[TOOLS_DIR_ENV_NAME];
@@ -48,7 +51,7 @@ export function resolveBinaryPatchTool(tool) {
48
51
  return configured;
49
52
  }
50
53
  throw new Error(`${TOOLS_DIR_ENV_NAME} is set to '${configuredDir}' but it does not contain '${tool}'. ` +
51
- `Build the tools with '${BUILD_SCRIPT_PATH}'.`);
54
+ `Build the tools with '${BUILD_COMMAND}'.`);
52
55
  }
53
56
  let directory = path.resolve(process.cwd());
54
57
  for (;;) {
@@ -63,7 +66,7 @@ export function resolveBinaryPatchTool(tool) {
63
66
  directory = parent;
64
67
  }
65
68
  throw new Error(`'${tool}' not found in any '${TOOLS_DIR_NAME}' directory at or above '${process.cwd()}'. ` +
66
- `Build it with '${BUILD_SCRIPT_PATH}', or set ${TOOLS_DIR_ENV_NAME} to a directory that contains it.`);
69
+ `Build it with '${BUILD_COMMAND}', or set ${TOOLS_DIR_ENV_NAME} to a directory that contains it.`);
67
70
  }
68
71
  /** Writes the patch that turns the bundle at `basePath` into the one at `targetPath`. */
69
72
  export function generatePatch(basePath, targetPath, patchPath) {
@@ -82,7 +82,7 @@ describe("generatePatch/applyPatch", () => {
82
82
  const previous = process.env.HDIFFPATCH_TOOLS_DIR;
83
83
  process.env.HDIFFPATCH_TOOLS_DIR = workPath("no-such-dir");
84
84
  try {
85
- expect(() => resolveBinaryPatchTool("hdiffz")).toThrow(/build-hdiffpatch\.sh/);
85
+ expect(() => resolveBinaryPatchTool("hdiffz")).toThrow(/npx code-push build-patch-tools/);
86
86
  }
87
87
  finally {
88
88
  if (previous === undefined) {
package/cli/index.ts CHANGED
@@ -34,6 +34,11 @@ import "./commands/showHistoryCommand/index.js";
34
34
  */
35
35
  import "./commands/initCommand/index.js";
36
36
 
37
+ /**
38
+ * npx code-push build-patch-tools
39
+ */
40
+ import "./commands/buildPatchToolsCommand/index.js";
41
+
37
42
  shell.set("-e");
38
43
  shell.set("+v");
39
44
 
@@ -101,7 +101,7 @@ describe("generatePatch/applyPatch", () => {
101
101
  const previous = process.env.HDIFFPATCH_TOOLS_DIR;
102
102
  process.env.HDIFFPATCH_TOOLS_DIR = workPath("no-such-dir");
103
103
  try {
104
- expect(() => resolveBinaryPatchTool("hdiffz")).toThrow(/build-hdiffpatch\.sh/);
104
+ expect(() => resolveBinaryPatchTool("hdiffz")).toThrow(/npx code-push build-patch-tools/);
105
105
  } finally {
106
106
  if (previous === undefined) {
107
107
  delete process.env.HDIFFPATCH_TOOLS_DIR;
@@ -37,15 +37,18 @@ export type BinaryPatchTool = 'hdiffz' | 'hpatchz';
37
37
  const HDIFFZ_OPTIONS = ['-f', '-m-6', '-c-zstd-21-24'];
38
38
  const HPATCHZ_OPTIONS = ['-f', '-m'];
39
39
 
40
- const TOOLS_DIR_ENV_NAME = 'HDIFFPATCH_TOOLS_DIR';
41
- const TOOLS_DIR_NAME = '.hdiffpatch-tools';
42
- const BUILD_SCRIPT_PATH = 'scripts/binary-patch/build-hdiffpatch.sh';
40
+ export const TOOLS_DIR_ENV_NAME = 'HDIFFPATCH_TOOLS_DIR';
41
+ export const TOOLS_DIR_NAME = '.hdiffpatch-tools';
42
+ const BUILD_COMMAND = 'npx code-push build-patch-tools';
43
43
 
44
44
  /**
45
45
  * Finds the hdiffz/hpatchz executable, looking at `HDIFFPATCH_TOOLS_DIR` first and
46
46
  * then at a `.hdiffpatch-tools` directory in the working directory or any directory
47
47
  * above it. The tools are built from source rather than installed as a package
48
48
  * dependency, so the error explains how to get them.
49
+ *
50
+ * `build-patch-tools` (`cli/commands/buildPatchToolsCommand/index.ts`) installs into the
51
+ * first place this looks; a change to the lookup order has to be mirrored there.
49
52
  */
50
53
  export function resolveBinaryPatchTool(tool: BinaryPatchTool): string {
51
54
  const configuredDir = process.env[TOOLS_DIR_ENV_NAME];
@@ -56,7 +59,7 @@ export function resolveBinaryPatchTool(tool: BinaryPatchTool): string {
56
59
  }
57
60
  throw new Error(
58
61
  `${TOOLS_DIR_ENV_NAME} is set to '${configuredDir}' but it does not contain '${tool}'. ` +
59
- `Build the tools with '${BUILD_SCRIPT_PATH}'.`,
62
+ `Build the tools with '${BUILD_COMMAND}'.`,
60
63
  );
61
64
  }
62
65
 
@@ -75,7 +78,7 @@ export function resolveBinaryPatchTool(tool: BinaryPatchTool): string {
75
78
 
76
79
  throw new Error(
77
80
  `'${tool}' not found in any '${TOOLS_DIR_NAME}' directory at or above '${process.cwd()}'. ` +
78
- `Build it with '${BUILD_SCRIPT_PATH}', or set ${TOOLS_DIR_ENV_NAME} to a directory that contains it.`,
81
+ `Build it with '${BUILD_COMMAND}', or set ${TOOLS_DIR_ENV_NAME} to a directory that contains it.`,
79
82
  );
80
83
  }
81
84
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bravemobile/react-native-code-push",
3
- "version": "13.1.0-beta.5",
3
+ "version": "13.1.0-beta.6",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "src/CodePush.js",
6
6
  "react-native": "src/CodePush.js",