xref: /expo/packages/@expo/cli/src/utils/git.ts (revision f2369006)
1import spawnAsync from '@expo/spawn-async';
2import chalk from 'chalk';
3
4import { env } from './env';
5import { isInteractive } from './interactive';
6import { confirmAsync } from './prompts';
7import * as Log from '../log';
8
9export async function maybeBailOnGitStatusAsync(): Promise<boolean> {
10  if (env.EXPO_NO_GIT_STATUS) {
11    Log.warn(
12      'Git status is dirty but the command will continue because EXPO_NO_GIT_STATUS is enabled...'
13    );
14    return false;
15  }
16  const isGitStatusClean = await validateGitStatusAsync();
17
18  // Give people a chance to bail out if git working tree is dirty
19  if (!isGitStatusClean) {
20    if (!isInteractive()) {
21      Log.warn(
22        `Git status is dirty but the command will continue because the terminal is not interactive.`
23      );
24      return false;
25    }
26
27    Log.log();
28    const answer = await confirmAsync({
29      message: `Would you like to proceed?`,
30    });
31
32    if (!answer) {
33      return true;
34    }
35
36    Log.log();
37  }
38  return false;
39}
40
41export async function validateGitStatusAsync(): Promise<boolean> {
42  let workingTreeStatus = 'unknown';
43  try {
44    const result = await spawnAsync('git', ['status', '--porcelain']);
45    workingTreeStatus = result.stdout === '' ? 'clean' : 'dirty';
46  } catch {
47    // Maybe git is not installed?
48    // Maybe this project is not using git?
49  }
50
51  if (workingTreeStatus === 'clean') {
52    Log.log(`Your git working tree is ${chalk.green('clean')}`);
53    Log.log('To revert the changes after this command completes, you can run the following:');
54    Log.log('  git clean --force && git reset --hard');
55    return true;
56  } else if (workingTreeStatus === 'dirty') {
57    Log.log(`${chalk.bold('Warning!')} Your git working tree is ${chalk.red('dirty')}.`);
58    Log.log(
59      `It's recommended to ${chalk.bold(
60        'commit all your changes before proceeding'
61      )}, so you can revert the changes made by this command if necessary.`
62    );
63  } else {
64    Log.log("We couldn't find a git repository in your project directory.");
65    Log.log("It's recommended to back up your project before proceeding.");
66  }
67
68  return false;
69}
70