-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
60 lines (52 loc) · 2.2 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import path from 'node:path'
import process from 'node:process'
import { EOL } from 'node:os'
import { exec as _exec } from 'node:child_process'
import { promisify } from 'node:util'
import { realpath } from 'node:fs/promises'
const exec = promisify(_exec)
/**
* Check if a local git repository is clean.
* Ignore files defined in [git-ignore-patterns](git-ignore-patterns),
* which contains commonly git-ignored files for node project.
* @param dir (optional). Default to `process.cwd()`
* @return Object { `isClean`, `untracked`, `unstaged`, `uncommitted` }
*/
export async function checkGitClean(dir = process.cwd()) {
try {
// the dir or its ancestor may contains symbolic link
const cwd = await realpath(dir)
const repoRoot = (await exec('git rev-parse --show-toplevel', {
cwd,
})).stdout.trim()
const currentDir = path.relative(repoRoot, cwd)
const excludeFilePath = path.resolve(__dirname, 'git-ignore-patterns')
// Get untracked files
const untrackedFiles = (await exec(`git ls-files --others --exclude-standard --exclude-from=${excludeFilePath}`, {
cwd,
})).stdout.trim()
// Get unstaged files
const unstagedFiles = (await exec('git diff --name-only', {
cwd,
})).stdout.trim()
// Get uncommitted files (staged but not committed)
const uncommittedFiles = (await exec('git diff --cached --name-only', {
cwd,
})).stdout.trim()
// Filter files in the current directory
const CURRENT_DIR_PATH_PREFIX = `${currentDir ? `${currentDir}/` : ''}`
const untracked = untrackedFiles.split(EOL).filter(v => !!v)
const unstaged = unstagedFiles.split(EOL).filter(file => file.startsWith(CURRENT_DIR_PATH_PREFIX)).map(file => file.replace(CURRENT_DIR_PATH_PREFIX, '')).filter(v => !!v)
const uncommitted = uncommittedFiles.split('\n').filter(file => file.startsWith(CURRENT_DIR_PATH_PREFIX)).map(file => file.replace(CURRENT_DIR_PATH_PREFIX, '')).filter(v => !!v)
const isClean = untracked.length === 0 && unstaged.length === 0 && uncommitted.length === 0
return {
isClean,
untracked,
unstaged,
uncommitted,
}
}
catch (error) {
throw new Error(`Failed to check in dir ${dir}. ${error}`)
}
}