Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 0 additions & 78 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,9 @@
"properties": "^1.2.1",
"protobufjs": "^7.6.3",
"q": "~1.5.1",
"recursive-fs": "2.1.0",
"rimraf": "^2.5.1",
"semver": "^7.5.3",
"simctl": "^2.0.3",
"slash": "1.0.0",
"superagent": "^8.0.9",
"temp": "^0.9.4",
"which": "^1.2.7",
"wordwrap": "1.0.0",
"xcode": "^3.0.1",
Expand Down
24 changes: 11 additions & 13 deletions script/command-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ const plist = require("plist");
const progress = require("progress");
const prompt = require("prompt");

const rimraf = require("rimraf");

const Table = require("cli-table");

const xcode = require("xcode");
Expand Down Expand Up @@ -293,15 +291,15 @@ function deleteConnectionInfoCache(printMessage: boolean = true): void {
}

function deleteFolder(folderPath: string): Promise<void> {
return Promise<void>((resolve, reject) => {
rimraf(folderPath, (err: any) => {
if (err) {
reject(err);
} else {
resolve(<void>null);
}
});
});
return Q(fs.promises.rm(folderPath, { recursive: true, force: true, maxRetries: 3 }));
}

async function deleteReactTempFolders(): globalThis.Promise<void> {
const tempFolder: string = os.tmpdir();
// An unreadable temp folder means there is nothing to delete
const names: string[] = await fs.promises.readdir(tempFolder).catch((): string[] => []);
const reactFolders: string[] = names.filter((name) => name.startsWith("react-"));
await Q.all(reactFolders.map((name) => deleteFolder(path.join(tempFolder, name))));
}

function deploymentAdd(command: cli.IDeploymentAddCommand): Promise<void> {
Expand Down Expand Up @@ -1397,7 +1395,7 @@ export const releaseExpo = (command: cli.IReleaseReactCommand): Promise<void> =>

return createEmptyTempReleaseFolder(outputFolder);
})
.then(() => deleteFolder(`${os.tmpdir()}/react-*`))
.then(() => deleteReactTempFolders())
.then(async () => {
const { isHermes, sourceMaps, bundleOptions } = await planBundle(command, outputFolder, bundleName, sourcemapOutputFolder);
await runExpoExportEmbedCommand(bundleOptions);
Expand Down Expand Up @@ -1487,7 +1485,7 @@ export const releaseReact = (command: cli.IReleaseReactCommand): Promise<void> =
})
// This is needed to clear the react native bundler cache:
// https://github.com/facebook/react-native/issues/4289
.then(() => deleteFolder(`${os.tmpdir()}/react-*`))
.then(() => deleteReactTempFolders())
.then(async () => {
const { isHermes, sourceMaps, bundleOptions } = await planBundle(command, outputFolder, bundleName, sourcemapOutputFolder);
await runReactNativeBundleCommand(bundleOptions, entryFile, isHermes);
Expand Down
36 changes: 7 additions & 29 deletions script/hash-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,9 @@ import * as path from "path";
import * as q from "q";
import * as stream from "stream";

// Do not throw an exception if either of these modules are missing, as they may not be needed by the
// consumer of this file.
// - recursiveFs: Only required for hashing of directories
// - yauzl: Only required for in-memory hashing of zip files
let recursiveFs, yauzl;

try {
recursiveFs = require("recursive-fs");
} catch (e) {}
try {
yauzl = require("yauzl");
} catch (e) {}
import * as yauzl from "yauzl";

import { listFiles } from "./utils/file-utils";

import Promise = q.Promise;
const HASH_ALGORITHM = "sha256";
Expand Down Expand Up @@ -102,18 +93,11 @@ export function generatePackageManifestFromZip(filePath: string): Promise<Packag
}

export function generatePackageManifestFromDirectory(directoryPath: string, basePath: string): Promise<PackageManifest> {
const deferred: q.Deferred<PackageManifest> = q.defer<PackageManifest>();
const fileHashesMap = new Map<string, string>();

recursiveFs.readdirr(directoryPath, (error?: any, directories?: string[], files?: string[]): void => {
if (error) {
deferred.reject(error);
return;
}

if (!files || files.length === 0) {
deferred.reject("Error: Can't sign the release because no files were found.");
return;
return q(listFiles(directoryPath)).then((files: string[]): Promise<PackageManifest> => {
if (files.length === 0) {
return q.reject<PackageManifest>("Error: Can't sign the release because no files were found.");
}

// Hash the files sequentially, because streaming them in parallel is not necessarily faster
Expand All @@ -128,14 +112,8 @@ export function generatePackageManifestFromDirectory(directoryPath: string, base
});
}, q(<void>null));

generateManifestPromise
.then(() => {
deferred.resolve(new PackageManifest(fileHashesMap));
}, deferred.reject)
.done();
return generateManifestPromise.then(() => new PackageManifest(fileHashesMap));
});

return deferred.promise;
}

export function hashFile(filePath: string): Promise<string> {
Expand Down
21 changes: 7 additions & 14 deletions script/management-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import * as os from "os";
import * as path from "path";
import Q = require("q");
import superagent = require("superagent");
import * as recursiveFs from "recursive-fs";
import * as yazl from "yazl";
import slash = require("slash");

import Promise = Q.Promise;

Expand All @@ -29,6 +27,7 @@ import {
BaseRelease,
} from "./types";
import { ReactNativePackageInfo } from "./types/rest-definitions";
import { listFiles, normalizePath } from "./utils/file-utils";

const packageJson = require("../../package.json");

Expand Down Expand Up @@ -465,15 +464,9 @@ class AccountManager {
private packageFileFromPath(filePath: string) {
let getPackageFilePromise: Promise<PackageFile>;
if (fs.lstatSync(filePath).isDirectory()) {
getPackageFilePromise = Promise<PackageFile>((resolve: (file: PackageFile) => void, reject: (reason: Error) => void): void => {
const directoryPath: string = filePath;

recursiveFs.readdirr(directoryPath, (error?: any, directories?: string[], files?: string[]) => {
if (error) {
reject(error);
return;
}

const directoryPath: string = filePath;
getPackageFilePromise = Q(listFiles(directoryPath)).then((files: string[]) =>
Promise<PackageFile>((resolve: (file: PackageFile) => void, reject: (reason: Error) => void): void => {
const baseDirectoryPath = path.dirname(directoryPath);
const fileName: string = this.generateRandomFilename(15) + ".zip";
const zipFile = new yazl.ZipFile();
Expand All @@ -493,14 +486,14 @@ class AccountManager {
for (let i = 0; i < files.length; ++i) {
const file: string = files[i];
// yazl does not like backslash (\) in the metadata path.
const relativePath: string = slash(path.relative(baseDirectoryPath, file));
const relativePath: string = normalizePath(path.relative(baseDirectoryPath, file));

zipFile.addFile(file, relativePath);
}

zipFile.end();
});
});
})
);
} else {
getPackageFilePromise = Q({ isTemporary: false, path: filePath });
}
Expand Down
2 changes: 1 addition & 1 deletion script/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default async function sign(privateKeyPath: string, updateContentsPath: s
updateContentsPath = copyFileToTmpDir(updateContentsPath);
}
} catch (error) {
Promise.reject(error);
return Promise.reject(error);
}

const signatureFilePath: string = path.join(updateContentsPath, METADATA_FILE_NAME);
Expand Down
27 changes: 22 additions & 5 deletions script/utils/file-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import * as rimraf from "rimraf";
import * as temp from "temp";
import * as yauzl from "yauzl";
import { pipeline } from "node:stream/promises";

Expand All @@ -25,9 +24,7 @@ export function fileExists(file: string): boolean {

export function copyFileToTmpDir(filePath: string): string {
if (!isDirectory(filePath)) {
const outputFolderPath: string = temp.mkdirSync("code-push");
rimraf.sync(outputFolderPath);
fs.mkdirSync(outputFolderPath);
const outputFolderPath: string = fs.mkdtempSync(path.join(os.tmpdir(), "code-push"));

const outputFilePath: string = path.join(outputFolderPath, path.basename(filePath));
fs.writeFileSync(outputFilePath, fs.readFileSync(filePath));
Expand All @@ -36,6 +33,26 @@ export function copyFileToTmpDir(filePath: string): string {
}
}

/**
* Lists the files under a folder, level by level, with paths joined by "/".
* Symlinks are listed as files, even when they point to a folder.
*/
export async function listFiles(directoryPath: string): Promise<string[]> {
let files: string[] = [];
let folders: string[] = [directoryPath];
while (folders.length > 0) {
const entries = (await Promise.all(folders.map(readFolder))).flat();
files = files.concat(entries.filter((entry) => !entry.isFolder).map((entry) => entry.path));
folders = entries.filter((entry) => entry.isFolder).map((entry) => entry.path);
}
return files;
}

async function readFolder(folder: string): Promise<{ path: string; isFolder: boolean }[]> {
const entries = await fs.promises.readdir(folder, { withFileTypes: true });
return entries.map((entry) => ({ path: `${folder}/${entry.name}`, isFolder: entry.isDirectory() }));
}

export function fileDoesNotExistOrIsDirectory(path: string): boolean {
try {
return isDirectory(path);
Expand Down
Loading
Loading