eoas 1.0.2 → 1.0.3
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.
- package/dist/commands/generate-certs.d.ts +8 -0
- package/dist/commands/generate-certs.js +90 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +113 -0
- package/dist/commands/publish.d.ts +18 -0
- package/dist/commands/publish.js +249 -0
- package/dist/lib/assets.d.ts +19 -0
- package/dist/lib/assets.js +90 -0
- package/dist/lib/auth.d.ts +6 -0
- package/dist/lib/auth.js +57 -0
- package/dist/lib/expoConfig.d.ts +23 -0
- package/dist/lib/expoConfig.js +198 -0
- package/dist/lib/log.d.ts +40 -0
- package/dist/lib/log.js +101 -0
- package/dist/lib/ora.d.ts +9 -0
- package/dist/lib/ora.js +103 -0
- package/dist/lib/package.d.ts +1 -0
- package/dist/lib/package.js +9 -0
- package/dist/lib/prompts.d.ts +13 -0
- package/dist/lib/prompts.js +68 -0
- package/dist/lib/repo.d.ts +6 -0
- package/dist/lib/repo.js +48 -0
- package/dist/lib/runtimeVersion.d.ts +42 -0
- package/dist/lib/runtimeVersion.js +116 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +7 -0
- package/dist/lib/vcs/clients/git.d.ts +31 -0
- package/dist/lib/vcs/clients/git.js +322 -0
- package/dist/lib/vcs/clients/gitNoCommit.d.ts +8 -0
- package/dist/lib/vcs/clients/gitNoCommit.js +42 -0
- package/dist/lib/vcs/clients/noVcs.d.ts +7 -0
- package/dist/lib/vcs/clients/noVcs.js +22 -0
- package/dist/lib/vcs/git.d.ts +13 -0
- package/dist/lib/vcs/git.js +60 -0
- package/dist/lib/vcs/index.d.ts +2 -0
- package/dist/lib/vcs/index.js +26 -0
- package/dist/lib/vcs/local.d.ts +19 -0
- package/dist/lib/vcs/local.js +85 -0
- package/dist/lib/vcs/vcs.d.ts +25 -0
- package/dist/lib/vcs/vcs.js +61 -0
- package/dist/lib/workflow.d.ts +4 -0
- package/dist/lib/workflow.js +40 -0
- package/package.json +6 -2
- package/.eslintignore +0 -1
- package/.eslintrc.js +0 -73
- package/.prettierrc +0 -9
- package/src/commands/generate-certs.ts +0 -95
- package/src/commands/init.ts +0 -117
- package/src/commands/publish.ts +0 -277
- package/src/index.d.ts +0 -7
- package/src/lib/assets.ts +0 -118
- package/src/lib/auth.ts +0 -67
- package/src/lib/expoConfig.ts +0 -265
- package/src/lib/log.ts +0 -122
- package/src/lib/ora.ts +0 -113
- package/src/lib/package.ts +0 -6
- package/src/lib/prompts.ts +0 -97
- package/src/lib/repo.ts +0 -62
- package/src/lib/runtimeVersion.ts +0 -177
- package/src/lib/utils.ts +0 -3
- package/src/lib/vcs/README.md +0 -1
- package/src/lib/vcs/clients/git.ts +0 -390
- package/src/lib/vcs/clients/gitNoCommit.ts +0 -45
- package/src/lib/vcs/clients/noVcs.ts +0 -23
- package/src/lib/vcs/git.ts +0 -68
- package/src/lib/vcs/index.ts +0 -25
- package/src/lib/vcs/local.ts +0 -88
- package/src/lib/vcs/vcs.ts +0 -90
- package/src/lib/workflow.ts +0 -47
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveRuntimeVersionAsync = exports.resolveRuntimeVersionUsingCLIAsync = exports.isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync = exports.expoUpdatesCommandAsync = exports.ExpoUpdatesCLICommandFailedError = exports.ExpoUpdatesCLIInvalidCommandError = exports.ExpoUpdatesCLIModuleNotFoundError = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
6
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
7
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
8
|
+
const resolve_from_1 = tslib_1.__importStar(require("resolve-from"));
|
|
9
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
10
|
+
const log_1 = tslib_1.__importStar(require("./log"));
|
|
11
|
+
class ExpoUpdatesCLIModuleNotFoundError extends Error {
|
|
12
|
+
}
|
|
13
|
+
exports.ExpoUpdatesCLIModuleNotFoundError = ExpoUpdatesCLIModuleNotFoundError;
|
|
14
|
+
class ExpoUpdatesCLIInvalidCommandError extends Error {
|
|
15
|
+
}
|
|
16
|
+
exports.ExpoUpdatesCLIInvalidCommandError = ExpoUpdatesCLIInvalidCommandError;
|
|
17
|
+
class ExpoUpdatesCLICommandFailedError extends Error {
|
|
18
|
+
}
|
|
19
|
+
exports.ExpoUpdatesCLICommandFailedError = ExpoUpdatesCLICommandFailedError;
|
|
20
|
+
async function expoUpdatesCommandAsync(projectDir, args, options) {
|
|
21
|
+
let expoUpdatesCli;
|
|
22
|
+
try {
|
|
23
|
+
expoUpdatesCli =
|
|
24
|
+
(0, resolve_from_1.silent)(projectDir, 'expo-updates/bin/cli') ??
|
|
25
|
+
(0, resolve_from_1.default)(projectDir, 'expo-updates/bin/cli.js');
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (e.code === 'MODULE_NOT_FOUND') {
|
|
29
|
+
throw new ExpoUpdatesCLIModuleNotFoundError(`The \`expo-updates\` package was not found. Follow the installation directions at ${(0, log_1.link)('https://docs.expo.dev/bare/installing-expo-modules/')}`);
|
|
30
|
+
}
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return (await (0, spawn_async_1.default)(expoUpdatesCli, args, {
|
|
35
|
+
stdio: 'pipe',
|
|
36
|
+
env: { ...process.env, ...options.env },
|
|
37
|
+
cwd: options.cwd,
|
|
38
|
+
})).stdout;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
if (e.stderr && typeof e.stderr === 'string') {
|
|
42
|
+
if (e.stderr.includes('Invalid command')) {
|
|
43
|
+
throw new ExpoUpdatesCLIInvalidCommandError(`The command specified by ${args} was not valid in the \`expo-updates\` CLI.`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new ExpoUpdatesCLICommandFailedError(e.stderr);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.expoUpdatesCommandAsync = expoUpdatesCommandAsync;
|
|
53
|
+
async function getExpoUpdatesPackageVersionIfInstalledAsync(projectDir) {
|
|
54
|
+
const maybePackageJson = resolve_from_1.default.silent(projectDir, 'expo-updates/package.json');
|
|
55
|
+
if (!maybePackageJson) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const { version } = await fs_extra_1.default.readJson(maybePackageJson);
|
|
59
|
+
return version ?? null;
|
|
60
|
+
}
|
|
61
|
+
async function isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir) {
|
|
62
|
+
const expoUpdatesPackageVersion = await getExpoUpdatesPackageVersionIfInstalledAsync(projectDir);
|
|
63
|
+
if (expoUpdatesPackageVersion === null) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (expoUpdatesPackageVersion.includes('canary')) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// Anything SDK 51 or greater uses the expo-updates CLI
|
|
70
|
+
return semver_1.default.gte(expoUpdatesPackageVersion, '0.25.4');
|
|
71
|
+
}
|
|
72
|
+
exports.isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync = isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync;
|
|
73
|
+
async function resolveRuntimeVersionUsingCLIAsync({ platform, workflow, projectDir, env, cwd, }) {
|
|
74
|
+
log_1.default.debug('Using expo-updates runtimeversion:resolve CLI for runtime version resolution');
|
|
75
|
+
const useDebugFingerprintSource = log_1.default.isDebug;
|
|
76
|
+
const extraArgs = useDebugFingerprintSource ? ['--debug'] : [];
|
|
77
|
+
const resolvedRuntimeVersionJSONResult = await expoUpdatesCommandAsync(projectDir, ['runtimeversion:resolve', '--platform', platform, '--workflow', workflow, ...extraArgs], { env, cwd });
|
|
78
|
+
const runtimeVersionResult = JSON.parse(resolvedRuntimeVersionJSONResult);
|
|
79
|
+
log_1.default.debug('runtimeversion:resolve output:');
|
|
80
|
+
log_1.default.debug(resolvedRuntimeVersionJSONResult);
|
|
81
|
+
return {
|
|
82
|
+
runtimeVersion: runtimeVersionResult.runtimeVersion ?? null,
|
|
83
|
+
expoUpdatesRuntimeFingerprint: runtimeVersionResult.fingerprintSources
|
|
84
|
+
? {
|
|
85
|
+
fingerprintSources: runtimeVersionResult.fingerprintSources,
|
|
86
|
+
isDebugFingerprintSource: useDebugFingerprintSource,
|
|
87
|
+
}
|
|
88
|
+
: null,
|
|
89
|
+
expoUpdatesRuntimeFingerprintHash: runtimeVersionResult.fingerprintSources
|
|
90
|
+
? runtimeVersionResult.runtimeVersion
|
|
91
|
+
: null,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
exports.resolveRuntimeVersionUsingCLIAsync = resolveRuntimeVersionUsingCLIAsync;
|
|
95
|
+
async function resolveRuntimeVersionAsync({ exp, platform, workflow, projectDir, env, cwd, }) {
|
|
96
|
+
if (!(await isModernExpoUpdatesCLIWithRuntimeVersionCommandSupportedAsync(projectDir))) {
|
|
97
|
+
// fall back to the previous behavior (using the @expo/config-plugins eas-cli dependency rather
|
|
98
|
+
// than the versioned @expo/config-plugins dependency in the project)
|
|
99
|
+
return {
|
|
100
|
+
runtimeVersion: await config_plugins_1.Updates.getRuntimeVersionNullableAsync(projectDir, exp, platform),
|
|
101
|
+
expoUpdatesRuntimeFingerprint: null,
|
|
102
|
+
expoUpdatesRuntimeFingerprintHash: null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
return await resolveRuntimeVersionUsingCLIAsync({ platform, workflow, projectDir, env, cwd });
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
// if expo-updates is not installed, there's no need for a runtime version in the build
|
|
110
|
+
if (e instanceof ExpoUpdatesCLIModuleNotFoundError) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
throw e;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.resolveRuntimeVersionAsync = resolveRuntimeVersionAsync;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isValidUpdateUrl(updateUrl: string): boolean;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Client } from '../vcs';
|
|
2
|
+
export default class GitClient extends Client {
|
|
3
|
+
private readonly maybeCwdOverride?;
|
|
4
|
+
constructor(maybeCwdOverride?: string | undefined);
|
|
5
|
+
ensureRepoExistsAsync(): Promise<void>;
|
|
6
|
+
commitAsync({ commitMessage, commitAllFiles, nonInteractive, }: {
|
|
7
|
+
commitMessage: string;
|
|
8
|
+
commitAllFiles?: boolean;
|
|
9
|
+
nonInteractive: boolean;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
isCommitRequiredAsync(): Promise<boolean>;
|
|
12
|
+
showChangedFilesAsync(): Promise<void>;
|
|
13
|
+
hasUncommittedChangesAsync(): Promise<boolean>;
|
|
14
|
+
getRootPathAsync(): Promise<string>;
|
|
15
|
+
makeShallowCopyAsync(destinationPath: string): Promise<void>;
|
|
16
|
+
getCommitHashAsync(): Promise<string | undefined>;
|
|
17
|
+
trackFileAsync(file: string): Promise<void>;
|
|
18
|
+
getBranchNameAsync(): Promise<string | null>;
|
|
19
|
+
getLastCommitMessageAsync(): Promise<string | null>;
|
|
20
|
+
showDiffAsync(): Promise<void>;
|
|
21
|
+
isFileUntrackedAsync(path: string): Promise<boolean>;
|
|
22
|
+
isFileIgnoredAsync(filePath: string): Promise<boolean>;
|
|
23
|
+
canGetLastCommitMessage(): boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks if git is configured to be case sensitive
|
|
27
|
+
* @returns {boolean | undefined}
|
|
28
|
+
* - boolean - is git case sensitive
|
|
29
|
+
* - undefined - case sensitivity is not configured and git is using default behavior
|
|
30
|
+
*/
|
|
31
|
+
export declare function isGitCaseSensitiveAsync(cwd: string | undefined): Promise<boolean | undefined>;
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isGitCaseSensitiveAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const PackageManagerUtils = tslib_1.__importStar(require("@expo/package-manager"));
|
|
6
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
7
|
+
const core_1 = require("@oclif/core");
|
|
8
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const log_1 = tslib_1.__importStar(require("../../log"));
|
|
11
|
+
const ora_1 = require("../../ora");
|
|
12
|
+
const prompts_1 = require("../../prompts");
|
|
13
|
+
const git_1 = require("../git");
|
|
14
|
+
const vcs_1 = require("../vcs");
|
|
15
|
+
class GitClient extends vcs_1.Client {
|
|
16
|
+
maybeCwdOverride;
|
|
17
|
+
constructor(maybeCwdOverride) {
|
|
18
|
+
super();
|
|
19
|
+
this.maybeCwdOverride = maybeCwdOverride;
|
|
20
|
+
}
|
|
21
|
+
async ensureRepoExistsAsync() {
|
|
22
|
+
try {
|
|
23
|
+
if (!(await (0, git_1.isGitInstalledAsync)())) {
|
|
24
|
+
log_1.default.error(`${chalk_1.default.bold('git')} command not found. Install it before proceeding or set ${chalk_1.default.bold('EAS_NO_VCS=1')} to use EAS CLI without Git (or any other version control system).`);
|
|
25
|
+
log_1.default.error((0, log_1.learnMore)('https://expo.fyi/eas-vcs-workflow'));
|
|
26
|
+
core_1.Errors.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
log_1.default.error(`${chalk_1.default.bold('git')} found, but ${chalk_1.default.bold('git --help')} exited with status ${error?.status}${error?.stderr ? `:` : '.'}`);
|
|
31
|
+
if (error?.stderr) {
|
|
32
|
+
log_1.default.error(error?.stderr);
|
|
33
|
+
}
|
|
34
|
+
log_1.default.error(`Repair your Git installation, or set ${chalk_1.default.bold('EAS_NO_VCS=1')} to use EAS CLI without Git (or any other version control system).`);
|
|
35
|
+
log_1.default.error((0, log_1.learnMore)('https://expo.fyi/eas-vcs-workflow'));
|
|
36
|
+
core_1.Errors.exit(1);
|
|
37
|
+
}
|
|
38
|
+
if (await (0, git_1.doesGitRepoExistAsync)(this.maybeCwdOverride)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
log_1.default.warn("It looks like you haven't initialized the git repository yet.");
|
|
42
|
+
log_1.default.warn('EAS requires you to use a git repository for your project.');
|
|
43
|
+
const cwd = process.cwd();
|
|
44
|
+
const repoRoot = PackageManagerUtils.resolveWorkspaceRoot(cwd) ?? cwd;
|
|
45
|
+
const confirmInit = await (0, prompts_1.confirmAsync)({
|
|
46
|
+
message: `Would you like us to run 'git init' in ${this.maybeCwdOverride ?? repoRoot} for you?`,
|
|
47
|
+
type: 'confirm',
|
|
48
|
+
name: 'confirmInit',
|
|
49
|
+
});
|
|
50
|
+
if (!confirmInit) {
|
|
51
|
+
throw new Error('A git repository is required for building your project. Initialize it and run this command again.');
|
|
52
|
+
}
|
|
53
|
+
await (0, spawn_async_1.default)('git', ['init'], { cwd: this.maybeCwdOverride ?? repoRoot });
|
|
54
|
+
log_1.default.log("We're going to make an initial commit for your repository.");
|
|
55
|
+
const { message } = await (0, prompts_1.promptAsync)({
|
|
56
|
+
type: 'text',
|
|
57
|
+
name: 'message',
|
|
58
|
+
message: 'Commit message:',
|
|
59
|
+
initial: 'Initial commit',
|
|
60
|
+
validate: (input) => input !== '',
|
|
61
|
+
});
|
|
62
|
+
await this.commitAsync({ commitAllFiles: true, commitMessage: message, nonInteractive: false });
|
|
63
|
+
}
|
|
64
|
+
async commitAsync({ commitMessage, commitAllFiles, nonInteractive = false, }) {
|
|
65
|
+
await ensureGitConfiguredAsync({ nonInteractive });
|
|
66
|
+
try {
|
|
67
|
+
if (commitAllFiles) {
|
|
68
|
+
await (0, spawn_async_1.default)('git', ['add', '-A'], {
|
|
69
|
+
cwd: this.maybeCwdOverride,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
await (0, spawn_async_1.default)('git', ['add', '-u'], {
|
|
73
|
+
cwd: this.maybeCwdOverride,
|
|
74
|
+
});
|
|
75
|
+
await (0, spawn_async_1.default)('git', ['commit', '-m', commitMessage], {
|
|
76
|
+
cwd: this.maybeCwdOverride,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
if (err?.stdout) {
|
|
81
|
+
log_1.default.error(err.stdout);
|
|
82
|
+
}
|
|
83
|
+
if (err?.stderr) {
|
|
84
|
+
log_1.default.error(err.stderr);
|
|
85
|
+
}
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async isCommitRequiredAsync() {
|
|
90
|
+
return await this.hasUncommittedChangesAsync();
|
|
91
|
+
}
|
|
92
|
+
async showChangedFilesAsync() {
|
|
93
|
+
const gitStatusOutput = await (0, git_1.gitStatusAsync)({
|
|
94
|
+
showUntracked: true,
|
|
95
|
+
cwd: this.maybeCwdOverride,
|
|
96
|
+
});
|
|
97
|
+
log_1.default.log(gitStatusOutput);
|
|
98
|
+
}
|
|
99
|
+
async hasUncommittedChangesAsync() {
|
|
100
|
+
const changes = await (0, git_1.gitStatusAsync)({ showUntracked: true, cwd: this.maybeCwdOverride });
|
|
101
|
+
return changes.length > 0;
|
|
102
|
+
}
|
|
103
|
+
async getRootPathAsync() {
|
|
104
|
+
return (await (0, spawn_async_1.default)('git', ['rev-parse', '--show-toplevel'], {
|
|
105
|
+
cwd: this.maybeCwdOverride,
|
|
106
|
+
})).stdout.trim();
|
|
107
|
+
}
|
|
108
|
+
async makeShallowCopyAsync(destinationPath) {
|
|
109
|
+
if (await this.hasUncommittedChangesAsync()) {
|
|
110
|
+
// it should already be checked before this function is called, but in case it wasn't
|
|
111
|
+
// we want to ensure that any changes were introduced by call to `setGitCaseSensitivityAsync`
|
|
112
|
+
throw new Error('You have some uncommitted changes in your repository.');
|
|
113
|
+
}
|
|
114
|
+
let gitRepoUri;
|
|
115
|
+
if (process.platform === 'win32') {
|
|
116
|
+
// getRootDirectoryAsync() will return C:/path/to/repo on Windows and path
|
|
117
|
+
// prefix should be file:///
|
|
118
|
+
gitRepoUri = `file:///${await this.getRootPathAsync()}`;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// getRootDirectoryAsync() will /path/to/repo, and path prefix should be
|
|
122
|
+
// file:/// so only file:// needs to be prepended
|
|
123
|
+
gitRepoUri = `file://${await this.getRootPathAsync()}`;
|
|
124
|
+
}
|
|
125
|
+
const isCaseSensitive = await isGitCaseSensitiveAsync(this.maybeCwdOverride);
|
|
126
|
+
await setGitCaseSensitivityAsync(true, this.maybeCwdOverride);
|
|
127
|
+
try {
|
|
128
|
+
if (await this.hasUncommittedChangesAsync()) {
|
|
129
|
+
log_1.default.error('Detected inconsistent filename casing between your local filesystem and git.');
|
|
130
|
+
log_1.default.error('This will likely cause your build to fail. Impacted files:');
|
|
131
|
+
await (0, spawn_async_1.default)('git', ['status', '--short'], {
|
|
132
|
+
stdio: 'inherit',
|
|
133
|
+
cwd: this.maybeCwdOverride,
|
|
134
|
+
});
|
|
135
|
+
log_1.default.newLine();
|
|
136
|
+
log_1.default.error(`Error: Resolve filename casing inconsistencies before proceeding. ${(0, log_1.learnMore)('https://expo.fyi/macos-ignorecase')}`);
|
|
137
|
+
throw new Error('You have some uncommitted changes in your repository.');
|
|
138
|
+
}
|
|
139
|
+
await (0, spawn_async_1.default)('git', ['clone', '--no-hardlinks', '--depth', '1', gitRepoUri, destinationPath], {
|
|
140
|
+
cwd: this.maybeCwdOverride,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await setGitCaseSensitivityAsync(isCaseSensitive, this.maybeCwdOverride);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async getCommitHashAsync() {
|
|
148
|
+
try {
|
|
149
|
+
return (await (0, spawn_async_1.default)('git', ['rev-parse', 'HEAD'], {
|
|
150
|
+
cwd: this.maybeCwdOverride,
|
|
151
|
+
})).stdout.trim();
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async trackFileAsync(file) {
|
|
158
|
+
await (0, spawn_async_1.default)('git', ['add', '--intent-to-add', file], {
|
|
159
|
+
cwd: this.maybeCwdOverride,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async getBranchNameAsync() {
|
|
163
|
+
try {
|
|
164
|
+
return (await (0, spawn_async_1.default)('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
165
|
+
cwd: this.maybeCwdOverride,
|
|
166
|
+
})).stdout.trim();
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async getLastCommitMessageAsync() {
|
|
173
|
+
try {
|
|
174
|
+
return (await (0, spawn_async_1.default)('git', ['--no-pager', 'log', '-1', '--pretty=%B'], {
|
|
175
|
+
cwd: this.maybeCwdOverride,
|
|
176
|
+
})).stdout.trim();
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async showDiffAsync() {
|
|
183
|
+
const outputTooLarge = (await (0, git_1.getGitDiffOutputAsync)(this.maybeCwdOverride)).split(/\r\n|\r|\n/).length > 100;
|
|
184
|
+
await (0, git_1.gitDiffAsync)({ withPager: outputTooLarge, cwd: this.maybeCwdOverride });
|
|
185
|
+
}
|
|
186
|
+
async isFileUntrackedAsync(path) {
|
|
187
|
+
const withUntrackedFiles = await (0, git_1.gitStatusAsync)({
|
|
188
|
+
showUntracked: true,
|
|
189
|
+
cwd: this.maybeCwdOverride,
|
|
190
|
+
});
|
|
191
|
+
const trackedFiles = await (0, git_1.gitStatusAsync)({ showUntracked: false, cwd: this.maybeCwdOverride });
|
|
192
|
+
const pathWithoutLeadingDot = path.replace(/^\.\//, ''); // remove leading './' from path
|
|
193
|
+
return (withUntrackedFiles.includes(pathWithoutLeadingDot) &&
|
|
194
|
+
!trackedFiles.includes(pathWithoutLeadingDot));
|
|
195
|
+
}
|
|
196
|
+
async isFileIgnoredAsync(filePath) {
|
|
197
|
+
try {
|
|
198
|
+
await (0, spawn_async_1.default)('git', ['check-ignore', '-q', filePath], {
|
|
199
|
+
cwd: this.maybeCwdOverride ?? path_1.default.normalize(await this.getRootPathAsync()),
|
|
200
|
+
});
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
canGetLastCommitMessage() {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.default = GitClient;
|
|
212
|
+
async function ensureGitConfiguredAsync({ nonInteractive, }) {
|
|
213
|
+
let usernameConfigured = true;
|
|
214
|
+
let emailConfigured = true;
|
|
215
|
+
try {
|
|
216
|
+
await (0, spawn_async_1.default)('git', ['config', '--get', 'user.name']);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
log_1.default.debug(err);
|
|
220
|
+
usernameConfigured = false;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
await (0, spawn_async_1.default)('git', ['config', '--get', 'user.email']);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
log_1.default.debug(err);
|
|
227
|
+
emailConfigured = false;
|
|
228
|
+
}
|
|
229
|
+
if (usernameConfigured && emailConfigured) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
log_1.default.warn(`You need to configure Git with your ${[
|
|
233
|
+
!usernameConfigured && 'username (user.name)',
|
|
234
|
+
!emailConfigured && 'email address (user.email)',
|
|
235
|
+
]
|
|
236
|
+
.filter(i => i)
|
|
237
|
+
.join(' and ')}`);
|
|
238
|
+
if (nonInteractive) {
|
|
239
|
+
throw new Error('Git cannot be configured automatically in non-interactive mode');
|
|
240
|
+
}
|
|
241
|
+
if (!usernameConfigured) {
|
|
242
|
+
const { username } = await (0, prompts_1.promptAsync)({
|
|
243
|
+
type: 'text',
|
|
244
|
+
name: 'username',
|
|
245
|
+
message: 'Username:',
|
|
246
|
+
validate: (input) => input !== '',
|
|
247
|
+
});
|
|
248
|
+
const spinner = (0, ora_1.ora)(`Running ${chalk_1.default.bold(`git config --local user.name ${username}`)}`).start();
|
|
249
|
+
try {
|
|
250
|
+
await (0, spawn_async_1.default)('git', ['config', '--local', 'user.name', username]);
|
|
251
|
+
spinner.succeed();
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
spinner.fail();
|
|
255
|
+
throw err;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (!emailConfigured) {
|
|
259
|
+
const { email } = await (0, prompts_1.promptAsync)({
|
|
260
|
+
type: 'text',
|
|
261
|
+
name: 'email',
|
|
262
|
+
message: 'Email address:',
|
|
263
|
+
validate: (input) => input !== '',
|
|
264
|
+
});
|
|
265
|
+
const spinner = (0, ora_1.ora)(`Running ${chalk_1.default.bold(`git config --local user.email ${email}`)}`).start();
|
|
266
|
+
try {
|
|
267
|
+
await (0, spawn_async_1.default)('git', ['config', '--local', 'user.email', email]);
|
|
268
|
+
spinner.succeed();
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
spinner.fail();
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Checks if git is configured to be case sensitive
|
|
278
|
+
* @returns {boolean | undefined}
|
|
279
|
+
* - boolean - is git case sensitive
|
|
280
|
+
* - undefined - case sensitivity is not configured and git is using default behavior
|
|
281
|
+
*/
|
|
282
|
+
async function isGitCaseSensitiveAsync(cwd) {
|
|
283
|
+
if (process.platform !== 'darwin') {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
const result = await (0, spawn_async_1.default)('git', ['config', '--get', 'core.ignorecase'], {
|
|
288
|
+
cwd,
|
|
289
|
+
});
|
|
290
|
+
const isIgnoreCaseEnabled = result.stdout.trim();
|
|
291
|
+
if (isIgnoreCaseEnabled === '') {
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
else if (isIgnoreCaseEnabled === 'true') {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
exports.isGitCaseSensitiveAsync = isGitCaseSensitiveAsync;
|
|
306
|
+
async function setGitCaseSensitivityAsync(enable, cwd) {
|
|
307
|
+
// we are assuming that if someone sets that on non-macos device then
|
|
308
|
+
// they know what they are doing
|
|
309
|
+
if (process.platform !== 'darwin') {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (enable === undefined) {
|
|
313
|
+
await (0, spawn_async_1.default)('git', ['config', '--unset', 'core.ignorecase'], {
|
|
314
|
+
cwd,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
await (0, spawn_async_1.default)('git', ['config', 'core.ignorecase', String(!enable)], {
|
|
319
|
+
cwd,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import GitClient from './git';
|
|
2
|
+
export default class GitNoCommitClient extends GitClient {
|
|
3
|
+
isCommitRequiredAsync(): Promise<boolean>;
|
|
4
|
+
getRootPathAsync(): Promise<string>;
|
|
5
|
+
makeShallowCopyAsync(destinationPath: string): Promise<void>;
|
|
6
|
+
isFileIgnoredAsync(filePath: string): Promise<boolean>;
|
|
7
|
+
trackFileAsync(file: string): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
+
const git_1 = tslib_1.__importDefault(require("./git"));
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("../../log"));
|
|
9
|
+
const local_1 = require("../local");
|
|
10
|
+
class GitNoCommitClient extends git_1.default {
|
|
11
|
+
async isCommitRequiredAsync() {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
async getRootPathAsync() {
|
|
15
|
+
return (await (0, spawn_async_1.default)('git', ['rev-parse', '--show-toplevel'])).stdout.trim();
|
|
16
|
+
}
|
|
17
|
+
async makeShallowCopyAsync(destinationPath) {
|
|
18
|
+
// normalize converts C:/some/path to C:\some\path on windows
|
|
19
|
+
const srcPath = path_1.default.normalize(await this.getRootPathAsync());
|
|
20
|
+
await (0, local_1.makeShallowCopyAsync)(srcPath, destinationPath);
|
|
21
|
+
}
|
|
22
|
+
async isFileIgnoredAsync(filePath) {
|
|
23
|
+
// normalize converts C:/some/path to C:\some\path on windows
|
|
24
|
+
const rootPath = path_1.default.normalize(await this.getRootPathAsync());
|
|
25
|
+
const ignore = new local_1.Ignore(rootPath);
|
|
26
|
+
await ignore.initIgnoreAsync();
|
|
27
|
+
return ignore.ignores(filePath);
|
|
28
|
+
}
|
|
29
|
+
async trackFileAsync(file) {
|
|
30
|
+
try {
|
|
31
|
+
await super.trackFileAsync(file);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// In the no commit workflow it doesn't matter if we fail to track changes,
|
|
35
|
+
// so we can ignore if this throws an exception
|
|
36
|
+
log_1.default.warn(`Unable to track ${chalk_1.default.bold(path_1.default.basename(file))} in Git. Proceeding without tracking.`);
|
|
37
|
+
log_1.default.warn(` Reason: the command ${chalk_1.default.bold(`"git add ${file}"`)} exited with an error.`);
|
|
38
|
+
log_1.default.newLine();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.default = GitNoCommitClient;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Client } from '../vcs';
|
|
2
|
+
export default class NoVcsClient extends Client {
|
|
3
|
+
getRootPathAsync(): Promise<string>;
|
|
4
|
+
makeShallowCopyAsync(destinationPath: string): Promise<void>;
|
|
5
|
+
isFileIgnoredAsync(filePath: string): Promise<boolean>;
|
|
6
|
+
canGetLastCommitMessage(): boolean;
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const local_1 = require("../local");
|
|
4
|
+
const vcs_1 = require("../vcs");
|
|
5
|
+
class NoVcsClient extends vcs_1.Client {
|
|
6
|
+
async getRootPathAsync() {
|
|
7
|
+
return (0, local_1.getRootPath)();
|
|
8
|
+
}
|
|
9
|
+
async makeShallowCopyAsync(destinationPath) {
|
|
10
|
+
const srcPath = (0, local_1.getRootPath)();
|
|
11
|
+
await (0, local_1.makeShallowCopyAsync)(srcPath, destinationPath);
|
|
12
|
+
}
|
|
13
|
+
async isFileIgnoredAsync(filePath) {
|
|
14
|
+
const ignore = new local_1.Ignore((0, local_1.getRootPath)());
|
|
15
|
+
await ignore.initIgnoreAsync();
|
|
16
|
+
return ignore.ignores(filePath);
|
|
17
|
+
}
|
|
18
|
+
canGetLastCommitMessage() {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = NoVcsClient;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function isGitInstalledAsync(): Promise<boolean>;
|
|
2
|
+
export declare function doesGitRepoExistAsync(cwd: string | undefined): Promise<boolean>;
|
|
3
|
+
interface GitStatusOptions {
|
|
4
|
+
showUntracked: boolean;
|
|
5
|
+
cwd: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare function gitStatusAsync({ showUntracked, cwd }: GitStatusOptions): Promise<string>;
|
|
8
|
+
export declare function getGitDiffOutputAsync(cwd: string | undefined): Promise<string>;
|
|
9
|
+
export declare function gitDiffAsync({ withPager, cwd, }: {
|
|
10
|
+
withPager?: boolean;
|
|
11
|
+
cwd: string | undefined;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitDiffAsync = exports.getGitDiffOutputAsync = exports.gitStatusAsync = exports.doesGitRepoExistAsync = exports.isGitInstalledAsync = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
|
|
6
|
+
async function isGitInstalledAsync() {
|
|
7
|
+
try {
|
|
8
|
+
await (0, spawn_async_1.default)('git', ['--help']);
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error.code === 'ENOENT') {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
exports.isGitInstalledAsync = isGitInstalledAsync;
|
|
19
|
+
async function doesGitRepoExistAsync(cwd) {
|
|
20
|
+
try {
|
|
21
|
+
await (0, spawn_async_1.default)('git', ['rev-parse', '--git-dir'], {
|
|
22
|
+
cwd,
|
|
23
|
+
});
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.doesGitRepoExistAsync = doesGitRepoExistAsync;
|
|
31
|
+
async function gitStatusAsync({ showUntracked, cwd }) {
|
|
32
|
+
return (await (0, spawn_async_1.default)('git', ['status', '-s', showUntracked ? '-uall' : '-uno'], {
|
|
33
|
+
cwd,
|
|
34
|
+
})).stdout;
|
|
35
|
+
}
|
|
36
|
+
exports.gitStatusAsync = gitStatusAsync;
|
|
37
|
+
async function getGitDiffOutputAsync(cwd) {
|
|
38
|
+
return (await (0, spawn_async_1.default)('git', ['--no-pager', 'diff'], {
|
|
39
|
+
cwd,
|
|
40
|
+
})).stdout;
|
|
41
|
+
}
|
|
42
|
+
exports.getGitDiffOutputAsync = getGitDiffOutputAsync;
|
|
43
|
+
async function gitDiffAsync({ withPager = false, cwd, }) {
|
|
44
|
+
const options = withPager ? [] : ['--no-pager'];
|
|
45
|
+
try {
|
|
46
|
+
await (0, spawn_async_1.default)('git', [...options, 'diff'], {
|
|
47
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
48
|
+
cwd,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (typeof error.message === 'string' && error.message.includes('SIGPIPE')) {
|
|
53
|
+
// This error is thrown when the user exits the pager with `q`.
|
|
54
|
+
// do nothing
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.gitDiffAsync = gitDiffAsync;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveVcsClient = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const git_1 = tslib_1.__importDefault(require("./clients/git"));
|
|
7
|
+
const gitNoCommit_1 = tslib_1.__importDefault(require("./clients/gitNoCommit"));
|
|
8
|
+
const noVcs_1 = tslib_1.__importDefault(require("./clients/noVcs"));
|
|
9
|
+
const NO_VCS_WARNING = `Using EAS CLI without version control system is not recommended, use this mode only if you know what you are doing.`;
|
|
10
|
+
function resolveVcsClient(requireCommit = false) {
|
|
11
|
+
if (process.env.EAS_NO_VCS) {
|
|
12
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
13
|
+
// This log might be printed before cli arguments are evaluated,
|
|
14
|
+
// so it needs to go to stderr in case command is run in JSON
|
|
15
|
+
// only mode.
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
console.error(chalk_1.default.yellow(NO_VCS_WARNING));
|
|
18
|
+
}
|
|
19
|
+
return new noVcs_1.default();
|
|
20
|
+
}
|
|
21
|
+
if (requireCommit) {
|
|
22
|
+
return new git_1.default();
|
|
23
|
+
}
|
|
24
|
+
return new gitNoCommit_1.default();
|
|
25
|
+
}
|
|
26
|
+
exports.resolveVcsClient = resolveVcsClient;
|