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