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