git-chopstick-core 0.1.0

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 (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/examples/get-status.ts +84 -0
  4. package/package.json +20 -0
  5. package/src/git/add.ts +16 -0
  6. package/src/git/apply.ts +154 -0
  7. package/src/git/authentication.ts +19 -0
  8. package/src/git/branch.ts +206 -0
  9. package/src/git/checkout-index.ts +40 -0
  10. package/src/git/checkout.ts +235 -0
  11. package/src/git/cherry-pick.ts +504 -0
  12. package/src/git/clean.ts +9 -0
  13. package/src/git/clone.ts +86 -0
  14. package/src/git/coerce-to-buffer.ts +4 -0
  15. package/src/git/coerce-to-string.ts +4 -0
  16. package/src/git/commit.ts +136 -0
  17. package/src/git/config.ts +392 -0
  18. package/src/git/core.ts +625 -0
  19. package/src/git/create-tail-stream.ts +36 -0
  20. package/src/git/credential.ts +83 -0
  21. package/src/git/description.ts +33 -0
  22. package/src/git/diff-check.ts +27 -0
  23. package/src/git/diff-index.ts +116 -0
  24. package/src/git/diff.ts +880 -0
  25. package/src/git/environment.ts +116 -0
  26. package/src/git/exec.ts +285 -0
  27. package/src/git/fetch.ts +141 -0
  28. package/src/git/for-each-ref.ts +160 -0
  29. package/src/git/format-patch.ts +17 -0
  30. package/src/git/git-delimiter-parser.ts +95 -0
  31. package/src/git/gitignore.ts +157 -0
  32. package/src/git/index.ts +36 -0
  33. package/src/git/init.ts +11 -0
  34. package/src/git/interpret-trailers.ts +176 -0
  35. package/src/git/lfs.ts +100 -0
  36. package/src/git/log.ts +376 -0
  37. package/src/git/merge-tree.ts +42 -0
  38. package/src/git/merge.ts +154 -0
  39. package/src/git/multi-operation-terminal-output.ts +68 -0
  40. package/src/git/pull.ts +130 -0
  41. package/src/git/push-terminal-chunk.ts +41 -0
  42. package/src/git/push.ts +119 -0
  43. package/src/git/rebase.ts +627 -0
  44. package/src/git/reflog.ts +127 -0
  45. package/src/git/refs.ts +63 -0
  46. package/src/git/remote.ts +143 -0
  47. package/src/git/reorder.ts +153 -0
  48. package/src/git/reset.ts +101 -0
  49. package/src/git/rev-list.ts +201 -0
  50. package/src/git/rev-parse.ts +92 -0
  51. package/src/git/revert.ts +55 -0
  52. package/src/git/rm.ts +31 -0
  53. package/src/git/show.ts +88 -0
  54. package/src/git/spawn.ts +38 -0
  55. package/src/git/squash.ts +173 -0
  56. package/src/git/stage.ts +97 -0
  57. package/src/git/stash.ts +302 -0
  58. package/src/git/status.ts +502 -0
  59. package/src/git/submodule.ts +212 -0
  60. package/src/git/tag.ts +134 -0
  61. package/src/git/update-index.ts +169 -0
  62. package/src/git/update-ref.ts +50 -0
  63. package/src/git/var.ts +42 -0
  64. package/src/git/worktree-include.ts +146 -0
  65. package/src/git/worktree.ts +219 -0
  66. package/src/lib/api.ts +7 -0
  67. package/src/lib/diff-parser.ts +249 -0
  68. package/src/lib/directory-exists.ts +10 -0
  69. package/src/lib/errno-exception.ts +12 -0
  70. package/src/lib/fatal-error.ts +23 -0
  71. package/src/lib/feature-flag.ts +29 -0
  72. package/src/lib/file-system.ts +7 -0
  73. package/src/lib/get-old-path.ts +11 -0
  74. package/src/lib/git/environment.ts +14 -0
  75. package/src/lib/git-perf.ts +3 -0
  76. package/src/lib/helpers/default-branch.ts +3 -0
  77. package/src/lib/helpers/path.ts +5 -0
  78. package/src/lib/hooks/with-hooks-env.ts +7 -0
  79. package/src/lib/merge.ts +3 -0
  80. package/src/lib/noop.ts +1 -0
  81. package/src/lib/patch-formatter.ts +18 -0
  82. package/src/lib/path-exists.ts +7 -0
  83. package/src/lib/progress/from-process.ts +10 -0
  84. package/src/lib/progress/index.ts +43 -0
  85. package/src/lib/progress/revert.ts +17 -0
  86. package/src/lib/rebase.ts +3 -0
  87. package/src/lib/remove-remote-prefix.ts +4 -0
  88. package/src/lib/resolve-git-proxy.ts +3 -0
  89. package/src/lib/round.ts +4 -0
  90. package/src/lib/split-buffer.ts +14 -0
  91. package/src/lib/status-parser.ts +188 -0
  92. package/src/lib/stores/helpers/find-default-remote.ts +3 -0
  93. package/src/lib/trampoline/trampoline-environment.ts +8 -0
  94. package/src/models/branch.ts +78 -0
  95. package/src/models/cherry-pick.ts +12 -0
  96. package/src/models/clone-options.ts +6 -0
  97. package/src/models/commit-identity.ts +35 -0
  98. package/src/models/commit.ts +44 -0
  99. package/src/models/computed-action.ts +6 -0
  100. package/src/models/diff/diff-data.ts +78 -0
  101. package/src/models/diff/diff-line.ts +36 -0
  102. package/src/models/diff/diff-selection.ts +165 -0
  103. package/src/models/diff/image-diff.ts +6 -0
  104. package/src/models/diff/image.ts +8 -0
  105. package/src/models/diff/index.ts +6 -0
  106. package/src/models/diff/raw-diff.ts +41 -0
  107. package/src/models/git-author.ts +16 -0
  108. package/src/models/manual-conflict-resolution.ts +4 -0
  109. package/src/models/merge.ts +6 -0
  110. package/src/models/multi-commit-operation.ts +6 -0
  111. package/src/models/progress.ts +67 -0
  112. package/src/models/rebase.ts +20 -0
  113. package/src/models/remote.ts +10 -0
  114. package/src/models/repository.ts +16 -0
  115. package/src/models/stash-entry.ts +25 -0
  116. package/src/models/status.ts +275 -0
  117. package/src/models/submodule.ts +13 -0
  118. package/src/models/worktree.ts +11 -0
  119. package/tsconfig.json +17 -0
@@ -0,0 +1,130 @@
1
+ import {
2
+ git,
3
+ gitRebaseArguments,
4
+ HookProgress,
5
+ IGitStringExecutionOptions,
6
+ TerminalOutput,
7
+ TerminalOutputCallback,
8
+ } from './core'
9
+ import { Repository } from '../models/repository'
10
+ import { IPullProgress } from '../models/progress'
11
+ import { PullProgressParser, executionOptionsWithProgress } from '../lib/progress'
12
+ import { IRemote } from '../models/remote'
13
+ import { envForRemoteOperation } from './environment'
14
+ import { getConfigValue } from './config'
15
+
16
+ /**
17
+ * Pull from the specified remote.
18
+ *
19
+ * @param repository - The repository in which the pull should take place
20
+ *
21
+ * @param remote - The name of the remote that should be pulled from
22
+ *
23
+ * @param progressCallback - An optional function which will be invoked
24
+ * with information about the current progress
25
+ * of the pull operation. When provided this enables
26
+ * the '--progress' command line flag for
27
+ * 'git pull'.
28
+ */
29
+ export async function pull(
30
+ repository: Repository,
31
+ remote: IRemote,
32
+ options?: {
33
+ progressCallback?: (progress: IPullProgress) => void
34
+ onHookProgress?: (progress: HookProgress) => void
35
+ onHookFailure?: (
36
+ hookName: string,
37
+ terminalOutput: TerminalOutput
38
+ ) => Promise<'abort' | 'ignore'>
39
+ onTerminalOutputAvailable?: TerminalOutputCallback
40
+ noVerify?: boolean
41
+ }
42
+ ): Promise<void> {
43
+ let opts: IGitStringExecutionOptions = {
44
+ env: await envForRemoteOperation(remote.url),
45
+ // git pull triggers merge or rebase hooks depending on config, instead of
46
+ // trying to check pull.rebase and friends we'll just intercept all possible
47
+ // hooks that could be run as part of a pull operation.
48
+ interceptHooks: [
49
+ 'pre-merge-commit',
50
+ 'prepare-commit-msg',
51
+ 'commit-msg',
52
+ 'post-merge',
53
+ 'pre-rebase',
54
+ 'pre-commit',
55
+ 'post-rewrite',
56
+ ],
57
+ }
58
+
59
+ if (options?.progressCallback) {
60
+ const title = `Pulling ${remote.name}`
61
+ const kind = 'pull'
62
+
63
+ opts = await executionOptionsWithProgress(
64
+ { ...opts, trackLFSProgress: true },
65
+ new PullProgressParser(),
66
+ progress => {
67
+ // In addition to progress output from the remote end and from
68
+ // git itself, the stderr output from pull contains information
69
+ // about ref updates. We don't need to bring those into the progress
70
+ // stream so we'll just punt on anything we don't know about for now.
71
+ if (progress.kind === 'context') {
72
+ if (!progress.text.startsWith('remote: Counting objects')) {
73
+ return
74
+ }
75
+ }
76
+
77
+ const description =
78
+ progress.kind === 'progress' ? progress.details.text : progress.text
79
+
80
+ const value = progress.percent
81
+
82
+ options?.progressCallback?.({
83
+ kind,
84
+ title,
85
+ description,
86
+ value,
87
+ remote: remote.name,
88
+ })
89
+ }
90
+ )
91
+
92
+ // Initial progress
93
+ options.progressCallback({ kind, title, value: 0, remote: remote.name })
94
+ }
95
+
96
+ const args = [
97
+ ...gitRebaseArguments(),
98
+ 'pull',
99
+ ...(await getDefaultPullDivergentBranchArguments(repository)),
100
+ '--recurse-submodules',
101
+ ...(options?.progressCallback ? ['--progress'] : []),
102
+ ...(options?.noVerify ? ['--no-verify'] : []),
103
+ remote.name,
104
+ ]
105
+
106
+ await git(args, repository.path, 'pull', opts)
107
+ }
108
+
109
+ /**
110
+ * Defaults the pull default for divergent paths to try to fast forward and if
111
+ * not perform a merge. Aka uses the flag --ff
112
+ *
113
+ * It checks whether the user has a config set for this already, if so, no need for
114
+ * default.
115
+ */
116
+ async function getDefaultPullDivergentBranchArguments(
117
+ repository: Repository
118
+ ): Promise<ReadonlyArray<string>> {
119
+ try {
120
+ const pullFF = await getConfigValue(repository, 'pull.ff')
121
+ return pullFF !== null ? [] : ['--ff']
122
+ } catch (e) {
123
+ console.error("Couldn't read 'pull.ff' config", e)
124
+ }
125
+
126
+ // If there is a failure in checking the config, we still want to use any
127
+ // config and not overwrite the user's set config behavior. This will show the
128
+ // git error if no config is set.
129
+ return []
130
+ }
@@ -0,0 +1,41 @@
1
+ import { coerceToString } from './coerce-to-string'
2
+
3
+ /**
4
+ * Appends a chunk of terminal output to a buffer while maintaining a maximum capacity.
5
+ *
6
+ * This function manages a rolling buffer of terminal output (combined stdout and stderr)
7
+ * by pushing new chunks and trimming from the beginning when the total character count
8
+ * exceeds the specified capacity. This ensures memory-bounded storage of terminal output
9
+ * for git operations.
10
+ *
11
+ * @param chunks - The array of string chunks representing the terminal output buffer.
12
+ * This array is mutated in place.
13
+ * @param capacity - The maximum number of characters to retain in the buffer.
14
+ * Note: this is character count, not byte count.
15
+ * @param chunk - The new chunk of terminal output to append, either as a Buffer or string.
16
+ *
17
+ * Intended to be used by git operations in core.ts to capture and limit terminal output.
18
+ * When the buffer exceeds capacity, chunks are removed from the beginning (oldest first),
19
+ * and partial chunks may be trimmed to fit exactly within the capacity limit.
20
+ */
21
+ export const pushTerminalChunk = (
22
+ chunks: string[],
23
+ capacity: number,
24
+ chunk: Buffer | string
25
+ ) => {
26
+ chunks.push(coerceToString(chunk))
27
+ let terminalOutputLength = chunks.reduce((acc, cur) => acc + cur.length, 0)
28
+
29
+ while (terminalOutputLength > capacity) {
30
+ const firstChunk = chunks[0]
31
+ const overrun = terminalOutputLength - capacity
32
+
33
+ if (overrun >= firstChunk.length) {
34
+ chunks.shift()
35
+ terminalOutputLength -= firstChunk.length
36
+ } else {
37
+ chunks[0] = firstChunk.substring(overrun)
38
+ terminalOutputLength -= overrun
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,119 @@
1
+ import { git, HookCallbackOptions, IGitStringExecutionOptions } from './core'
2
+ import { Repository } from '../models/repository'
3
+ import { IPushProgress } from '../models/progress'
4
+ import { PushProgressParser, executionOptionsWithProgress } from '../lib/progress'
5
+ import { IRemote } from '../models/remote'
6
+ import { envForRemoteOperation } from './environment'
7
+ import { Branch } from '../models/branch'
8
+
9
+ export type PushOptions = {
10
+ /**
11
+ * Force-push the branch without losing changes in the remote that
12
+ * haven't been fetched.
13
+ *
14
+ * See https://git-scm.com/docs/git-push#Documentation/git-push.txt---no-force-with-lease
15
+ */
16
+ readonly forceWithLease?: boolean
17
+
18
+ /** A branch to push instead of the current branch */
19
+ readonly branch?: Branch
20
+
21
+ readonly noVerify?: boolean
22
+ } & HookCallbackOptions
23
+
24
+ /**
25
+ * Push from the remote to the branch, optionally setting the upstream.
26
+ *
27
+ * @param repository - The repository from which to push
28
+ *
29
+ * @param account - The account to use when authenticating with the remote
30
+ *
31
+ * @param remote - The remote to push the specified branch to
32
+ *
33
+ * @param localBranch - The local branch to push
34
+ *
35
+ * @param remoteBranch - The remote branch to push to
36
+ *
37
+ * @param tagsToPush - The tags to push along with the branch.
38
+ *
39
+ * @param options - Optional customizations for the push execution.
40
+ * see PushOptions for more information.
41
+ *
42
+ * @param progressCallback - An optional function which will be invoked
43
+ * with information about the current progress
44
+ * of the push operation. When provided this enables
45
+ * the '--progress' command line flag for
46
+ * 'git push'.
47
+ */
48
+ export async function push(
49
+ repository: Repository,
50
+ remote: IRemote,
51
+ localBranch: string,
52
+ remoteBranch: string | null,
53
+ tagsToPush: ReadonlyArray<string> | null,
54
+ options?: PushOptions,
55
+ progressCallback?: (progress: IPushProgress) => void
56
+ ): Promise<void> {
57
+ const args = [
58
+ 'push',
59
+ remote.name,
60
+ remoteBranch ? `${localBranch}:${remoteBranch}` : localBranch,
61
+ ]
62
+
63
+ if (tagsToPush !== null) {
64
+ args.push(...tagsToPush)
65
+ }
66
+ if (!remoteBranch) {
67
+ args.push('--set-upstream')
68
+ } else if (options?.forceWithLease) {
69
+ args.push('--force-with-lease')
70
+ }
71
+
72
+ if (options?.noVerify) {
73
+ args.push('--no-verify')
74
+ }
75
+
76
+ let opts: IGitStringExecutionOptions = {
77
+ env: await envForRemoteOperation(remote.url),
78
+ interceptHooks: ['pre-push'],
79
+ onHookProgress: options?.onHookProgress,
80
+ onHookFailure: options?.onHookFailure,
81
+ onTerminalOutputAvailable: options?.onTerminalOutputAvailable,
82
+ }
83
+
84
+ if (progressCallback) {
85
+ args.push('--progress')
86
+ const title = `Pushing to ${remote.name}`
87
+ const kind = 'push'
88
+
89
+ opts = await executionOptionsWithProgress(
90
+ { ...opts, trackLFSProgress: true },
91
+ new PushProgressParser(),
92
+ progress => {
93
+ const description =
94
+ progress.kind === 'progress' ? progress.details.text : progress.text
95
+ const value = progress.percent
96
+
97
+ progressCallback({
98
+ kind,
99
+ title,
100
+ description,
101
+ value,
102
+ remote: remote.name,
103
+ branch: localBranch,
104
+ })
105
+ }
106
+ )
107
+
108
+ // Initial progress
109
+ progressCallback({
110
+ kind: 'push',
111
+ title,
112
+ value: 0,
113
+ remote: remote.name,
114
+ branch: localBranch,
115
+ })
116
+ }
117
+
118
+ await git(args, repository.path, 'push', opts)
119
+ }