-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunstaged.ts
More file actions
195 lines (189 loc) · 6.53 KB
/
unstaged.ts
File metadata and controls
195 lines (189 loc) · 6.53 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/**
* @fileoverview "Edited but not yet staged" helpers — `git diff` over the
* working tree only. Excludes index-staged changes and untracked paths;
* use `changed.ts` for the broader view or `staged.ts` for the index.
*/
import { normalizePath } from '../paths/normalize'
import { ArrayPrototypeIncludes } from '../primordials/array'
import { getGitDiffSpawnArgs, innerDiff, innerDiffSync } from './_internal'
import { getCachedRealpath, getCwd, getPath } from './repo'
import type { GitDiffOptions } from './types'
/**
* Get unstaged modified files (changes not yet staged for commit).
*
* Uses `git diff --name-only` which returns only unstaged modifications
* to tracked files. Does NOT include:
* - Untracked files (new files not added to git)
* - Staged changes (files added with `git add`)
*
* This is a focused check for uncommitted changes to existing tracked files.
* Useful for detecting work-in-progress modifications before staging.
*
* @param options - Options controlling path format and filtering.
* @returns Promise resolving to array of unstaged file paths.
*
* @example
* ```typescript
* // Get unstaged files
* const files = await getUnstagedFiles()
* // => ['src/foo.ts', 'src/bar.ts']
*
* // After staging some files
* await spawn('git', ['add', 'src/foo.ts'])
* const files = await getUnstagedFiles()
* // => ['src/bar.ts'] (foo.ts no longer included)
*
* // Get absolute paths
* const files = await getUnstagedFiles({ absolute: true })
* // => ['/path/to/repo/src/bar.ts']
* ```
*/
export async function getUnstagedFiles(
options?: GitDiffOptions | undefined,
): Promise<string[]> {
const args = getGitDiffSpawnArgs(options?.cwd).unstaged
return await innerDiff(args, options)
}
/**
* Get unstaged modified files (changes not yet staged for commit).
*
* Synchronous version of `getUnstagedFiles()`. Uses `git diff --name-only`
* which returns only unstaged modifications to tracked files. Does NOT include:
* - Untracked files (new files not added to git)
* - Staged changes (files added with `git add`)
*
* This is a focused check for uncommitted changes to existing tracked files.
* Useful for detecting work-in-progress modifications before staging.
*
* @param options - Options controlling path format and filtering.
* @returns Array of unstaged file paths.
*
* @example
* ```typescript
* // Get unstaged files
* const files = getUnstagedFilesSync()
* // => ['src/foo.ts', 'src/bar.ts']
*
* // After staging some files
* spawnSync('git', ['add', 'src/foo.ts'])
* const files = getUnstagedFilesSync()
* // => ['src/bar.ts'] (foo.ts no longer included)
*
* // Get absolute paths
* const files = getUnstagedFilesSync({ absolute: true })
* // => ['/path/to/repo/src/bar.ts']
* ```
*/
export function getUnstagedFilesSync(
options?: GitDiffOptions | undefined,
): string[] {
const args = getGitDiffSpawnArgs(options?.cwd).unstaged
return innerDiffSync(args, options)
}
/**
* Check if a file or directory has unstaged changes.
*
* Checks if the given pathname has modifications that are not yet staged
* for commit (changes not added with `git add`). Does NOT include:
* - Staged changes (already added with `git add`)
* - Untracked files (new files not in git)
*
* For directories, returns `true` if ANY file within the directory has
* unstaged changes.
*
* Symlinks in the pathname and cwd are automatically resolved using
* `fs.realpathSync()` before comparison.
*
* @param pathname - File or directory path to check.
* @param options - Options for the git diff check.
* @returns Promise resolving to `true` if path has unstaged changes, `false` otherwise.
*
* @example
* ```typescript
* // Check if file has unstaged changes
* const unstaged = await isUnstaged('src/foo.ts')
* // => true
*
* // After staging the file
* await spawn('git', ['add', 'src/foo.ts'])
* const unstaged = await isUnstaged('src/foo.ts')
* // => false
*
* // Check directory
* const unstaged = await isUnstaged('src/')
* // => true (if any file in src/ has unstaged changes)
* ```
*/
export async function isUnstaged(
pathname: string,
options?: GitDiffOptions | undefined,
): Promise<boolean> {
const files = await getUnstagedFiles({
__proto__: null,
...options,
absolute: false,
})
const path = getPath()
// Resolve pathname to handle symlinks before computing relative path (using cache).
const resolvedPathname = getCachedRealpath(pathname)
// options.cwd-passed arm exercised when caller specifies cwd; default getCwd().
/* c8 ignore start */
const baseCwd = options?.cwd ? getCachedRealpath(options['cwd']) : getCwd()
/* c8 ignore stop */
const relativePath = normalizePath(path.relative(baseCwd, resolvedPathname))
return ArrayPrototypeIncludes(files, relativePath)
}
/**
* Check if a file or directory has unstaged changes.
*
* Synchronous version of `isUnstaged()`. Checks if the given pathname has
* modifications that are not yet staged for commit (changes not added with
* `git add`). Does NOT include:
* - Staged changes (already added with `git add`)
* - Untracked files (new files not in git)
*
* For directories, returns `true` if ANY file within the directory has
* unstaged changes.
*
* Symlinks in the pathname and cwd are automatically resolved using
* `fs.realpathSync()` before comparison.
*
* @param pathname - File or directory path to check.
* @param options - Options for the git diff check.
* @returns `true` if path has unstaged changes, `false` otherwise.
*
* @example
* ```typescript
* // Check if file has unstaged changes
* const unstaged = isUnstagedSync('src/foo.ts')
* // => true
*
* // After staging the file
* spawnSync('git', ['add', 'src/foo.ts'])
* const unstaged = isUnstagedSync('src/foo.ts')
* // => false
*
* // Check directory
* const unstaged = isUnstagedSync('src/')
* // => true (if any file in src/ has unstaged changes)
* ```
*/
export function isUnstagedSync(
pathname: string,
options?: GitDiffOptions | undefined,
): boolean {
const files = getUnstagedFilesSync({
__proto__: null,
...options,
absolute: false,
})
const path = getPath()
// Resolve pathname to handle symlinks before computing relative path (using cache).
const resolvedPathname = getCachedRealpath(pathname)
// options.cwd-passed arm exercised when caller specifies cwd; default getCwd().
/* c8 ignore start */
const baseCwd = options?.cwd ? getCachedRealpath(options['cwd']) : getCwd()
/* c8 ignore stop */
const relativePath = normalizePath(path.relative(baseCwd, resolvedPathname))
return ArrayPrototypeIncludes(files, relativePath)
}