git-chopstick-core 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +42 -10
  2. package/dist/git/apply.d.ts +1 -1
  3. package/dist/git/apply.js +1 -1
  4. package/dist/git/apply.js.map +1 -1
  5. package/dist/git/environment.d.ts +1 -1
  6. package/dist/git/environment.js +1 -1
  7. package/dist/git/environment.js.map +1 -1
  8. package/dist/git/exec.js.map +1 -1
  9. package/dist/git/gitignore.js +1 -1
  10. package/dist/git/gitignore.js.map +1 -1
  11. package/dist/git/index.d.ts +1 -0
  12. package/dist/git/index.js +3 -0
  13. package/dist/git/index.js.map +1 -1
  14. package/dist/lib/fatal-error.d.ts +1 -1
  15. package/dist/lib/fatal-error.js +1 -1
  16. package/dist/lib/fatal-error.js.map +1 -1
  17. package/dist/lib/progress/from-process.js.map +1 -1
  18. package/dist/lib/progress/index.d.ts +5 -5
  19. package/dist/lib/progress/index.js +5 -5
  20. package/dist/lib/progress/index.js.map +1 -1
  21. package/dist/lib/progress/revert.d.ts +1 -1
  22. package/dist/lib/progress/revert.js +1 -1
  23. package/dist/lib/progress/revert.js.map +1 -1
  24. package/dist/lib/status-parser.js +0 -12
  25. package/dist/lib/status-parser.js.map +1 -1
  26. package/dist/models/repository.d.ts +1 -1
  27. package/dist/models/repository.js +1 -1
  28. package/dist/models/repository.js.map +1 -1
  29. package/package.json +39 -9
  30. package/src/git/add.ts +0 -16
  31. package/src/git/apply.ts +0 -154
  32. package/src/git/authentication.ts +0 -20
  33. package/src/git/branch.ts +0 -206
  34. package/src/git/checkout-index.ts +0 -40
  35. package/src/git/checkout.ts +0 -235
  36. package/src/git/cherry-pick.ts +0 -504
  37. package/src/git/clean.ts +0 -9
  38. package/src/git/clone.ts +0 -86
  39. package/src/git/coerce-to-buffer.ts +0 -4
  40. package/src/git/coerce-to-string.ts +0 -4
  41. package/src/git/commit.ts +0 -136
  42. package/src/git/config.ts +0 -392
  43. package/src/git/core.ts +0 -625
  44. package/src/git/create-tail-stream.ts +0 -36
  45. package/src/git/credential.ts +0 -83
  46. package/src/git/description.ts +0 -33
  47. package/src/git/diff-check.ts +0 -27
  48. package/src/git/diff-index.ts +0 -116
  49. package/src/git/diff.ts +0 -880
  50. package/src/git/environment.ts +0 -116
  51. package/src/git/exec.ts +0 -285
  52. package/src/git/fetch.ts +0 -141
  53. package/src/git/for-each-ref.ts +0 -160
  54. package/src/git/format-patch.ts +0 -17
  55. package/src/git/git-delimiter-parser.ts +0 -95
  56. package/src/git/gitignore.ts +0 -157
  57. package/src/git/index.ts +0 -46
  58. package/src/git/init.ts +0 -11
  59. package/src/git/interpret-trailers.ts +0 -176
  60. package/src/git/lfs.ts +0 -100
  61. package/src/git/log.ts +0 -376
  62. package/src/git/merge-tree.ts +0 -42
  63. package/src/git/merge.ts +0 -154
  64. package/src/git/multi-operation-terminal-output.ts +0 -68
  65. package/src/git/pull.ts +0 -130
  66. package/src/git/push-terminal-chunk.ts +0 -41
  67. package/src/git/push.ts +0 -119
  68. package/src/git/rebase.ts +0 -627
  69. package/src/git/reflog.ts +0 -127
  70. package/src/git/refs.ts +0 -63
  71. package/src/git/remote.ts +0 -143
  72. package/src/git/reorder.ts +0 -153
  73. package/src/git/reset.ts +0 -101
  74. package/src/git/rev-list.ts +0 -201
  75. package/src/git/rev-parse.ts +0 -92
  76. package/src/git/revert.ts +0 -55
  77. package/src/git/rm.ts +0 -31
  78. package/src/git/show.ts +0 -88
  79. package/src/git/spawn.ts +0 -38
  80. package/src/git/squash.ts +0 -173
  81. package/src/git/stage.ts +0 -97
  82. package/src/git/stash.ts +0 -302
  83. package/src/git/status.ts +0 -502
  84. package/src/git/submodule.ts +0 -212
  85. package/src/git/tag.ts +0 -134
  86. package/src/git/update-index.ts +0 -169
  87. package/src/git/update-ref.ts +0 -50
  88. package/src/git/var.ts +0 -42
  89. package/src/git/worktree-include.ts +0 -146
  90. package/src/git/worktree.ts +0 -219
  91. package/src/index.ts +0 -11
  92. package/src/lib/api.ts +0 -7
  93. package/src/lib/diff-parser.ts +0 -249
  94. package/src/lib/directory-exists.ts +0 -10
  95. package/src/lib/errno-exception.ts +0 -12
  96. package/src/lib/fatal-error.ts +0 -23
  97. package/src/lib/feature-flag.ts +0 -29
  98. package/src/lib/file-system.ts +0 -7
  99. package/src/lib/get-old-path.ts +0 -11
  100. package/src/lib/git/environment.ts +0 -14
  101. package/src/lib/git-perf.ts +0 -3
  102. package/src/lib/helpers/default-branch.ts +0 -3
  103. package/src/lib/helpers/path.ts +0 -5
  104. package/src/lib/hooks/with-hooks-env.ts +0 -7
  105. package/src/lib/merge.ts +0 -3
  106. package/src/lib/noop.ts +0 -1
  107. package/src/lib/patch-formatter.ts +0 -18
  108. package/src/lib/path-exists.ts +0 -7
  109. package/src/lib/progress/from-process.ts +0 -10
  110. package/src/lib/progress/index.ts +0 -43
  111. package/src/lib/progress/revert.ts +0 -17
  112. package/src/lib/rebase.ts +0 -3
  113. package/src/lib/remove-remote-prefix.ts +0 -4
  114. package/src/lib/resolve-git-proxy.ts +0 -3
  115. package/src/lib/round.ts +0 -4
  116. package/src/lib/split-buffer.ts +0 -14
  117. package/src/lib/status-parser.ts +0 -188
  118. package/src/lib/stores/helpers/find-default-remote.ts +0 -3
  119. package/src/lib/trampoline/trampoline-environment.ts +0 -8
  120. package/src/models/branch.ts +0 -78
  121. package/src/models/cherry-pick.ts +0 -12
  122. package/src/models/clone-options.ts +0 -6
  123. package/src/models/commit-identity.ts +0 -35
  124. package/src/models/commit.ts +0 -44
  125. package/src/models/computed-action.ts +0 -6
  126. package/src/models/diff/diff-data.ts +0 -78
  127. package/src/models/diff/diff-line.ts +0 -36
  128. package/src/models/diff/diff-selection.ts +0 -165
  129. package/src/models/diff/image-diff.ts +0 -6
  130. package/src/models/diff/image.ts +0 -8
  131. package/src/models/diff/index.ts +0 -6
  132. package/src/models/diff/raw-diff.ts +0 -41
  133. package/src/models/git-author.ts +0 -16
  134. package/src/models/index.ts +0 -36
  135. package/src/models/manual-conflict-resolution.ts +0 -4
  136. package/src/models/merge.ts +0 -6
  137. package/src/models/multi-commit-operation.ts +0 -6
  138. package/src/models/progress.ts +0 -67
  139. package/src/models/rebase.ts +0 -20
  140. package/src/models/remote.ts +0 -10
  141. package/src/models/repository.ts +0 -16
  142. package/src/models/stash-entry.ts +0 -25
  143. package/src/models/status.ts +0 -275
  144. package/src/models/submodule.ts +0 -13
  145. package/src/models/worktree.ts +0 -11
package/src/git/stage.ts DELETED
@@ -1,97 +0,0 @@
1
- import { Repository } from '../models/repository.js'
2
- import {
3
- WorkingDirectoryFileChange,
4
- isConflictedFileStatus,
5
- GitStatusEntry,
6
- isConflictWithMarkers,
7
- } from '../models/status.js'
8
- import { ManualConflictResolution } from '../models/manual-conflict-resolution.js'
9
- import { assertNever } from '../lib/fatal-error.js'
10
- import { removeConflictedFile } from './rm.js'
11
- import { checkoutConflictedFile } from './checkout.js'
12
- import { addConflictedFile } from './add.js'
13
-
14
- /**
15
- * Stages a file with the given manual resolution method. Useful for resolving binary conflicts at commit-time.
16
- *
17
- * @param repository
18
- * @param file conflicted file to stage
19
- * @param manualResolution method to resolve the conflict of file
20
- * @returns true if successful, false if something went wrong
21
- */
22
- export async function stageManualConflictResolution(
23
- repository: Repository,
24
- file: WorkingDirectoryFileChange,
25
- manualResolution: ManualConflictResolution
26
- ): Promise<void> {
27
- const { status } = file
28
- // if somehow the file isn't in a conflicted state
29
- if (!isConflictedFileStatus(status)) {
30
- console.error(`tried to manually resolve unconflicted file (${file.path})`)
31
- return
32
- }
33
-
34
- if (isConflictWithMarkers(status) && status.conflictMarkerCount === 0) {
35
- // If somehow the user used the Desktop UI to solve the conflict via ours/theirs
36
- // but afterwards resolved manually the conflicts via an editor, used the manually
37
- // resolved file.
38
- return
39
- }
40
-
41
- const chosen =
42
- manualResolution === ManualConflictResolution.theirs
43
- ? status.entry.them
44
- : status.entry.us
45
-
46
- const addedInBoth =
47
- status.entry.us === GitStatusEntry.Added &&
48
- status.entry.them === GitStatusEntry.Added
49
-
50
- if (chosen === GitStatusEntry.UpdatedButUnmerged || addedInBoth) {
51
- await checkoutConflictedFile(repository, file, manualResolution)
52
- }
53
-
54
- switch (chosen) {
55
- case GitStatusEntry.Deleted:
56
- return removeConflictedFile(repository, file)
57
- case GitStatusEntry.Added:
58
- case GitStatusEntry.UpdatedButUnmerged:
59
- return addConflictedFile(repository, file)
60
- default:
61
- assertNever(chosen, 'unaccounted for git status entry possibility')
62
- }
63
- }
64
-
65
- /**
66
- * Stages all resolved conflict files before a checkout operation to prevent
67
- * "error: you need to resolve your current index first" from git.
68
- *
69
- * Handles two kinds of resolved conflicts:
70
- * - Text conflicts resolved in an external editor (conflictMarkerCount === 0)
71
- * - Manual conflicts where the user chose ours/theirs in the Desktop UI
72
- */
73
- export async function stageResolvedConflictFiles(
74
- repository: Repository,
75
- files: ReadonlyArray<WorkingDirectoryFileChange>,
76
- manualResolutions: ReadonlyMap<string, ManualConflictResolution>
77
- ): Promise<void> {
78
- for (const file of files) {
79
- const { status } = file
80
- if (!isConflictedFileStatus(status)) {
81
- continue
82
- }
83
-
84
- const manualResolution = manualResolutions.get(file.path)
85
-
86
- if (manualResolution !== undefined) {
87
- // Binary/manual conflict resolved via Desktop UI — stage it
88
- await stageManualConflictResolution(repository, file, manualResolution)
89
- } else if (
90
- isConflictWithMarkers(status) &&
91
- status.conflictMarkerCount === 0
92
- ) {
93
- // Text conflict resolved in external editor — stage it
94
- await addConflictedFile(repository, file)
95
- }
96
- }
97
- }
package/src/git/stash.ts DELETED
@@ -1,302 +0,0 @@
1
- import { GitError as DugiteError } from './exec.js'
2
- import { git, GitError } from './core.js'
3
- import { Repository } from '../models/repository.js'
4
- import {
5
- IStashEntry,
6
- StashedChangesLoadStates,
7
- StashedFileChanges,
8
- } from '../models/stash-entry.js'
9
- import {
10
- WorkingDirectoryFileChange,
11
- CommittedFileChange,
12
- } from '../models/status.js'
13
- import { parseRawLogWithNumstat } from './log.js'
14
- import { stageFiles } from './update-index.js'
15
- import { Branch } from '../models/branch.js'
16
- import { createLogParser } from './git-delimiter-parser.js'
17
- import { coerceToString } from './coerce-to-string.js'
18
-
19
- export const DesktopStashEntryMarker = '!!GitHub_Desktop'
20
-
21
- /**
22
- * RegEx for determining if a stash entry is created by Desktop
23
- *
24
- * This is done by looking for a magic string with the following
25
- * format: `!!GitHub_Desktop<branch>`
26
- */
27
- const desktopStashEntryMessageRe = /!!GitHub_Desktop<(.+)>$/
28
-
29
- type StashResult = {
30
- /** The stash entries created by Desktop */
31
- readonly desktopEntries: ReadonlyArray<IStashEntry>
32
-
33
- /**
34
- * The total amount of stash entries,
35
- * i.e. stash entries created both by Desktop and outside of Desktop
36
- */
37
- readonly stashEntryCount: number
38
- }
39
-
40
- /**
41
- * Get the list of stash entries created by Desktop in the current repository
42
- * using the default ordering of refs (which is LIFO ordering),
43
- * as well as the total amount of stash entries.
44
- */
45
- export async function getStashes(repository: Repository): Promise<StashResult> {
46
- const { formatArgs, parse } = createLogParser({
47
- name: '%gD',
48
- stashSha: '%H',
49
- message: '%gs',
50
- tree: '%T',
51
- parents: '%P',
52
- })
53
-
54
- const result = await git(
55
- ['log', '-g', ...formatArgs, 'refs/stash', '--'],
56
- repository.path,
57
- 'getStashEntries',
58
- { successExitCodes: new Set([0, 128]) }
59
- )
60
-
61
- // There's no refs/stashes reflog in the repository or it's not
62
- // even a repository. In either case we don't care
63
- if (result.exitCode === 128) {
64
- return { desktopEntries: [], stashEntryCount: 0 }
65
- }
66
-
67
- const desktopEntries: Array<IStashEntry> = []
68
- const files: StashedFileChanges = { kind: StashedChangesLoadStates.NotLoaded }
69
-
70
- const entries = parse(result.stdout)
71
-
72
- for (const { name, message, stashSha, tree, parents } of entries) {
73
- const branchName = extractBranchFromMessage(message)
74
-
75
- if (branchName !== null) {
76
- desktopEntries.push({
77
- name,
78
- stashSha,
79
- branchName,
80
- tree,
81
- parents: parents.length > 0 ? parents.split(' ') : [],
82
- files,
83
- })
84
- }
85
- }
86
-
87
- return { desktopEntries, stashEntryCount: entries.length - 1 }
88
- }
89
-
90
- /**
91
- * Moves a stash entry to a different branch by means of creating
92
- * a new stash entry associated with the new branch and dropping the old
93
- * stash entry.
94
- */
95
- export async function moveStashEntry(
96
- repository: Repository,
97
- { stashSha, parents, tree }: IStashEntry,
98
- branchName: string
99
- ) {
100
- const message = `On ${branchName}: ${createDesktopStashMessage(branchName)}`
101
- const parentArgs = parents.flatMap(p => ['-p', p])
102
-
103
- const { stdout: commitId } = await git(
104
- ['commit-tree', ...parentArgs, '-m', message, '--no-gpg-sign', tree],
105
- repository.path,
106
- 'moveStashEntryToBranch'
107
- )
108
-
109
- await git(
110
- ['stash', 'store', '-m', message, commitId.trim()],
111
- repository.path,
112
- 'moveStashEntryToBranch'
113
- )
114
-
115
- await dropDesktopStashEntry(repository, stashSha)
116
- }
117
-
118
- /**
119
- * Returns the last Desktop created stash entry for the given branch
120
- */
121
- export async function getLastDesktopStashEntryForBranch(
122
- repository: Repository,
123
- branch: Branch | string
124
- ) {
125
- const stash = await getStashes(repository)
126
- const branchName = typeof branch === 'string' ? branch : branch.name
127
-
128
- // Since stash objects are returned in a LIFO manner, the first
129
- // entry found is guaranteed to be the last entry created
130
- return (
131
- stash.desktopEntries.find(stash => stash.branchName === branchName) || null
132
- )
133
- }
134
-
135
- /** Creates a stash entry message that indicates the entry was created by Desktop */
136
- export function createDesktopStashMessage(branchName: string) {
137
- return `${DesktopStashEntryMarker}<${branchName}>`
138
- }
139
-
140
- /**
141
- * Stash the working directory changes for the current branch
142
- */
143
- export async function createDesktopStashEntry(
144
- repository: Repository,
145
- branch: Branch | string,
146
- untrackedFilesToStage: ReadonlyArray<WorkingDirectoryFileChange>,
147
- selectedFiles: ReadonlyArray<string> | null
148
- ): Promise<boolean> {
149
- // We must ensure that no untracked files are present before stashing
150
- // See https://github.com/desktop/desktop/pull/8085
151
- // First ensure that all changes in file are selected
152
- // (in case the user has not explicitly checked the checkboxes for the untracked files)
153
- const fullySelectedUntrackedFiles = untrackedFilesToStage
154
- .filter(f => (selectedFiles ? selectedFiles.includes(f.path) : true))
155
- .map(x => x.withIncludeAll(true))
156
- await stageFiles(repository, fullySelectedUntrackedFiles)
157
-
158
- const branchName = typeof branch === 'string' ? branch : branch.name
159
- const message = createDesktopStashMessage(branchName)
160
- const args = ['stash', 'push', '-m', message]
161
- if (selectedFiles) {
162
- args.push(...selectedFiles)
163
- }
164
-
165
- const result = await git(args, repository.path, 'createStashEntry').catch(
166
- e => {
167
- // Note: 2024: Here be dragons. As I converted this code to get rid of the
168
- // successExitCode use I got curious about the assumptions made in the
169
- // following logic. It assumes that as long as the exit code for `git
170
- // stash push` is 1 and there are no lines beginning with "error: " then
171
- // a stash was created. That didn't hold up to a quick read of the stash
172
- // code. For example, running git stash push in an unborn repository will
173
- // get you an exit code of 1 but no stash was created:
174
- //
175
- // % git stash push -m foo ; echo $?
176
- // You do not have the initial commit yet
177
- // 1
178
- //
179
- // I'm not going to mess with this now but I felt the need to document
180
- // my findings should I or any other brave soul choose to tackle this in
181
- // the future.
182
- if (e instanceof GitError && e.result.exitCode === 1) {
183
- // search for any line starting with `error:` - /m here to ensure this is
184
- // applied to each line, without needing to split the text
185
- const errorPrefixRe = /^error: /m
186
-
187
- const matches = errorPrefixRe.exec(coerceToString(e.result.stderr))
188
- if (matches !== null && matches.length > 0) {
189
- // rethrow, because these messages should prevent the stash from being created
190
- return Promise.reject(e)
191
- }
192
-
193
- // if no error messages were emitted by Git, we should log but continue because
194
- // a valid stash was created and this should not interfere with the checkout
195
-
196
- console.info(
197
- `[createDesktopStashEntry] a stash was created successfully but exit code ${result.exitCode} reported. stderr: ${result.stderr}`
198
- )
199
- return e.result
200
- }
201
- return Promise.reject(e)
202
- }
203
- )
204
-
205
- // Stash doesn't consider it an error that there aren't any local changes to save.
206
- if (result.stdout === 'No local changes to save\n') {
207
- return false
208
- }
209
-
210
- return true
211
- }
212
-
213
- async function getStashEntryMatchingSha(repository: Repository, sha: string) {
214
- const stash = await getStashes(repository)
215
- return stash.desktopEntries.find(e => e.stashSha === sha) || null
216
- }
217
-
218
- /**
219
- * Removes the given stash entry if it exists
220
- *
221
- * @param stashSha the SHA that identifies the stash entry
222
- */
223
- export async function dropDesktopStashEntry(
224
- repository: Repository,
225
- stashSha: string
226
- ) {
227
- const entryToDelete = await getStashEntryMatchingSha(repository, stashSha)
228
-
229
- if (entryToDelete !== null) {
230
- const args = ['stash', 'drop', entryToDelete.name]
231
- await git(args, repository.path, 'dropStashEntry')
232
- }
233
- }
234
-
235
- /**
236
- * Pops the stash entry identified by matching `stashSha` to its commit hash.
237
- *
238
- * To see the commit hash of stash entry, run
239
- * `git log -g refs/stash --pretty="%nentry: %gd%nsubject: %gs%nhash: %H%n"`
240
- * in a repo with some stash entries.
241
- */
242
- export async function popStashEntry(
243
- repository: Repository,
244
- stashSha: string
245
- ): Promise<void> {
246
- // ignoring these git errors for now, this will change when we start
247
- // implementing the stash conflict flow
248
- const expectedErrors = new Set<DugiteError>([DugiteError.MergeConflicts])
249
- const stashToPop = await getStashEntryMatchingSha(repository, stashSha)
250
-
251
- if (stashToPop !== null) {
252
- const args = ['stash', 'pop', '--quiet', `${stashToPop.name}`]
253
- await git(args, repository.path, 'popStashEntry', {
254
- expectedErrors,
255
- }).catch(e => {
256
- // popping a stashes that create conflicts in the working directory
257
- // report an exit code of `1` and are not dropped after being applied.
258
- // so, we check for this case and drop them manually unless there's
259
- // anything in stderr as that could have prevented the stash from being
260
- // popped. Not the greatest approach but stash isn't very communicative
261
- if (
262
- e instanceof GitError &&
263
- e.result.exitCode === 1 &&
264
- e.result.stderr.length === 0
265
- ) {
266
- console.info(
267
- `[popStashEntry] a stash was popped successfully but exit code ${e.result.exitCode} reported.`
268
- )
269
- // bye bye
270
- return dropDesktopStashEntry(repository, stashSha)
271
- }
272
- return Promise.reject(e)
273
- })
274
- }
275
- }
276
-
277
- function extractBranchFromMessage(message: string): string | null {
278
- const match = desktopStashEntryMessageRe.exec(message)
279
- return match === null || match[1].length === 0 ? null : match[1]
280
- }
281
-
282
- /** Get the files that were changed in the given stash commit */
283
- export async function getStashedFiles(
284
- repository: Repository,
285
- stashSha: string
286
- ): Promise<ReadonlyArray<CommittedFileChange>> {
287
- const args = [
288
- 'stash',
289
- 'show',
290
- stashSha,
291
- '--raw',
292
- '--numstat',
293
- '-z',
294
- '--format=format:',
295
- '--no-show-signature',
296
- '--',
297
- ]
298
-
299
- const { stdout } = await git(args, repository.path, 'getStashedFiles')
300
-
301
- return parseRawLogWithNumstat(stdout, stashSha, `${stashSha}^`).files
302
- }