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/tag.ts DELETED
@@ -1,134 +0,0 @@
1
- import { git } from './core.js'
2
- import { Repository } from '../models/repository.js'
3
- import { IRemote } from '../models/remote.js'
4
- import { envForRemoteOperation } from './environment.js'
5
-
6
- /**
7
- * Create a new tag on the given target commit.
8
- *
9
- * @param repository - The repository in which to create the new tag.
10
- * @param name - The name of the new tag.
11
- * @param targetCommitSha - The SHA of the commit where the new tag will live on.
12
- */
13
- export async function createTag(
14
- repository: Repository,
15
- name: string,
16
- targetCommitSha: string
17
- ): Promise<void> {
18
- const args = ['tag', '-a', '-m', '', name, targetCommitSha]
19
-
20
- await git(args, repository.path, 'createTag')
21
- }
22
-
23
- /**
24
- * Delete a tag.
25
- *
26
- * @param repository - The repository in which to create the new tag.
27
- * @param name - The name of the tag to delete.
28
- */
29
- export async function deleteTag(
30
- repository: Repository,
31
- name: string
32
- ): Promise<void> {
33
- const args = ['tag', '-d', name]
34
-
35
- await git(args, repository.path, 'deleteTag')
36
- }
37
-
38
- /**
39
- * Gets all the local tags. Returns a Map with the tag name and the commit it points to.
40
- *
41
- * @param repository The repository in which to get all the tags from.
42
- */
43
- export async function getAllTags(
44
- repository: Repository
45
- ): Promise<Map<string, string>> {
46
- const args = ['show-ref', '--tags', '-d']
47
-
48
- const tags = await git(args, repository.path, 'getAllTags', {
49
- successExitCodes: new Set([0, 1]), // when there are no tags, git exits with 1.
50
- })
51
-
52
- const tagsArray: Array<[string, string]> = tags.stdout
53
- .split('\n')
54
- .filter(line => line !== '')
55
- .map(line => {
56
- const [commitSha, rawTagName] = line.split(' ')
57
-
58
- // Normalize tag names by removing the leading ref/tags/ and the trailing ^{}.
59
- //
60
- // git show-ref returns two entries for annotated tags:
61
- // deadbeef refs/tags/annotated-tag
62
- // de510b99 refs/tags/annotated-tag^{}
63
- //
64
- // The first entry sha correspond to the blob object of the annotation, while the second
65
- // entry corresponds to the actual commit where the tag was created.
66
- // By normalizing the tag name we can make sure that the commit sha gets stored in the returned
67
- // Map of commits (since git will always print the entry with the commit sha at the end).
68
- const tagName = rawTagName
69
- .replace(/^refs\/tags\//, '')
70
- .replace(/\^\{\}$/, '')
71
-
72
- return [tagName, commitSha]
73
- })
74
-
75
- return new Map(tagsArray)
76
- }
77
-
78
- /**
79
- * Fetches the tags that will get pushed to the remote repository (it does a network request).
80
- *
81
- * @param repository - The repository in which to check for unpushed tags
82
- * @param account - The account to use when authenticating with the remote
83
- * @param remote - The remote to check for unpushed tags
84
- * @param branchName - The branch that will be used on the push command
85
- */
86
- export async function fetchTagsToPush(
87
- repository: Repository,
88
- remote: IRemote,
89
- branchName: string
90
- ): Promise<ReadonlyArray<string>> {
91
- const args = [
92
- 'push',
93
- remote.name,
94
- branchName,
95
- '--follow-tags',
96
- '--dry-run',
97
- '--no-verify',
98
- '--porcelain',
99
- ]
100
-
101
- const result = await git(args, repository.path, 'fetchTagsToPush', {
102
- env: await envForRemoteOperation(remote.url),
103
- successExitCodes: new Set([0, 1, 128]),
104
- })
105
-
106
- if (result.exitCode !== 0 && result.exitCode !== 1) {
107
- // Only when the exit code of git is 0 or 1, its stdout is parseable.
108
- // In other cases, we just rethrow the error so our memoization layer
109
- // doesn't cache it indefinitely.
110
- throw result.gitError
111
- }
112
-
113
- const lines = result.stdout.split('\n')
114
- let currentLine = 1
115
- const unpushedTags = []
116
-
117
- // the last line of this porcelain command is always 'Done'
118
- while (currentLine < lines.length && lines[currentLine] !== 'Done') {
119
- const line = lines[currentLine]
120
- const parts = line.split('\t')
121
-
122
- if (parts[0] === '*' && parts[2] === '[new tag]') {
123
- const [tagName] = parts[1].split(':')
124
-
125
- if (tagName !== undefined) {
126
- unpushedTags.push(tagName.replace(/^refs\/tags\//, ''))
127
- }
128
- }
129
-
130
- currentLine++
131
- }
132
-
133
- return unpushedTags
134
- }
@@ -1,169 +0,0 @@
1
- import { git } from './core.js'
2
- import { Repository } from '../models/repository.js'
3
- import { DiffSelectionType } from '../models/diff/index.js'
4
- import { applyPatchToIndex } from './apply.js'
5
- import {
6
- WorkingDirectoryFileChange,
7
- AppFileStatusKind,
8
- } from '../models/status.js'
9
-
10
- interface IUpdateIndexOptions {
11
- /**
12
- * Whether or not to add a file when it exists in the working directory
13
- * but not in the index. Defaults to true (note that this differs from the
14
- * default behavior of Git which is to ignore new files).
15
- *
16
- * @default true
17
- */
18
- add?: boolean
19
-
20
- /**
21
- * Whether or not to remove a file when it exists in the index but not
22
- * in the working directory. Defaults to true (note that this differs from
23
- * the default behavior of Git which is to ignore removed files).
24
- *
25
- * @default true
26
- */
27
- remove?: boolean
28
-
29
- /**
30
- * Whether or not to forcefully remove a file from the index even though it
31
- * exists in the working directory. This implies remove.
32
- *
33
- * @default false
34
- */
35
- forceRemove?: boolean
36
-
37
- /**
38
- * Whether or not to replace conflicting entries in the index with that of
39
- * the working directory. Imagine the following scenario
40
- *
41
- * $ touch foo && git update-index --add foo && git commit -m 'foo'
42
- * $ rm foo && mkdir foo && echo "bar" > foo/bar
43
- * $ git update-index --add foo/bar
44
- * error: 'foo/bar' appears as both a file and as a directory
45
- * error: foo/bar: cannot add to the index - missing --add option?
46
- * fatal: Unable to process path foo/bar
47
- *
48
- * Replace ignores this conflict and overwrites the index with the
49
- * newly created directory, causing the original foo file to be deleted
50
- * in the index. This behavior matches what `git add` would do in a similar
51
- * scenario.
52
- *
53
- * @default true
54
- */
55
- replace?: boolean
56
- }
57
-
58
- /**
59
- * Updates the index with file contents from the working tree. This method
60
- * is a noop when no paths are provided.
61
- *
62
- * @param paths A list of paths which are to be updated with file contents and
63
- * status from the working directory.
64
- *
65
- * @param options See the IUpdateIndexOptions interface for more details.
66
- */
67
- async function updateIndex(
68
- repository: Repository,
69
- paths: ReadonlyArray<string>,
70
- options: IUpdateIndexOptions = {}
71
- ) {
72
- if (paths.length === 0) {
73
- return
74
- }
75
-
76
- const args = ['update-index']
77
-
78
- if (options.add !== false) {
79
- args.push('--add')
80
- }
81
-
82
- if (options.remove !== false || options.forceRemove === true) {
83
- args.push('--remove')
84
- }
85
-
86
- if (options.forceRemove) {
87
- args.push('--force-remove')
88
- }
89
-
90
- if (options.replace !== false) {
91
- args.push('--replace')
92
- }
93
-
94
- args.push('-z', '--stdin')
95
-
96
- await git(args, repository.path, 'updateIndex', {
97
- stdin: paths.join('\0'),
98
- })
99
- }
100
-
101
- /**
102
- * Stage all the given files by either staging the entire path or by applying
103
- * a patch.
104
- *
105
- * Note that prior to stageFiles the index has been completely reset,
106
- * the job of this function is to set up the index in such a way that it
107
- * reflects what the user has selected in the app.
108
- */
109
- export async function stageFiles(
110
- repository: Repository,
111
- files: ReadonlyArray<WorkingDirectoryFileChange>
112
- ): Promise<void> {
113
- const normal = []
114
- const oldRenamed = []
115
- const partial = []
116
- const deletedFiles = []
117
-
118
- for (const file of files) {
119
- if (file.selection.getSelectionType() === DiffSelectionType.All) {
120
- normal.push(file.path)
121
- if (file.status.kind === AppFileStatusKind.Renamed) {
122
- oldRenamed.push(file.status.oldPath)
123
- } else if (file.status.kind === AppFileStatusKind.Deleted) {
124
- deletedFiles.push(file.path)
125
- }
126
- } else {
127
- partial.push(file)
128
- }
129
- }
130
-
131
- // Staging files happens in three steps.
132
- //
133
- // In the first step we run through all of the renamed files, or
134
- // more specifically the source files (old) that were renamed and
135
- // forcefully remove them from the index. We do this in order to handle
136
- // the scenario where a file has been renamed and a new file has been
137
- // created in its original position. Think of it like this
138
- //
139
- // $ touch foo && git add foo && git commit -m 'foo'
140
- // $ git mv foo bar
141
- // $ echo "I'm a new foo" > foo
142
- //
143
- // Now we have a file which is of type Renamed that has its path set
144
- // to 'bar' and its oldPath set to 'foo'. But there's a new file called
145
- // foo in the repository. So if the user selects the 'foo -> bar' change
146
- // but not the new 'foo' file for inclusion in this commit we don't
147
- // want to add the new 'foo', we just want to recreate the move in the
148
- // index. We do this by forcefully removing the old path from the index
149
- // and then later (in step 2) stage the new file.
150
- await updateIndex(repository, oldRenamed, { forceRemove: true })
151
-
152
- // In the second step we update the index to match
153
- // the working directory in the case of new, modified, deleted,
154
- // and copied files as well as the destination paths for renamed
155
- // paths.
156
- await updateIndex(repository, normal)
157
-
158
- // This third step will only happen if we have files that have been marked
159
- // for deletion. This covers us for files that were blown away in the last
160
- // updateIndex call
161
- await updateIndex(repository, deletedFiles, { forceRemove: true })
162
-
163
- // Finally we run through all files that have partial selections.
164
- // We don't care about renamed or not here since applyPatchToIndex
165
- // has logic to support that scenario.
166
- for (const file of partial) {
167
- await applyPatchToIndex(repository, file)
168
- }
169
- }
@@ -1,50 +0,0 @@
1
- import { git } from './core.js'
2
- import { Repository } from '../models/repository.js'
3
-
4
- /**
5
- * Update the ref to a new value.
6
- *
7
- * @param repository - The repository in which the ref exists.
8
- * @param ref - The ref to update. Must be fully qualified
9
- * (e.g., `refs/heads/NAME`).
10
- * @param oldValue - The value we expect the ref to have currently. If it
11
- * doesn't match, the update will be aborted.
12
- * @param newValue - The new value for the ref.
13
- * @param reason - The reflog entry.
14
- */
15
- export async function updateRef(
16
- repository: Repository,
17
- ref: string,
18
- oldValue: string,
19
- newValue: string,
20
- reason: string
21
- ): Promise<void> {
22
- await git(
23
- ['update-ref', ref, newValue, oldValue, '-m', reason],
24
- repository.path,
25
- 'updateRef'
26
- )
27
- }
28
-
29
- /**
30
- * Remove a ref.
31
- *
32
- * @param repository - The repository in which the ref exists.
33
- * @param ref - The ref to remove. Should be fully qualified, but may also be 'HEAD'.
34
- * @param reason - The reflog entry (optional). Note that this is only useful when
35
- * deleting the HEAD reference as deleting any other reference will
36
- * implicitly delete the reflog file for that reference as well.
37
- */
38
- export async function deleteRef(
39
- repository: Repository,
40
- ref: string,
41
- reason?: string
42
- ) {
43
- const args = ['update-ref', '-d', ref]
44
-
45
- if (reason !== undefined) {
46
- args.push('-m', reason)
47
- }
48
-
49
- await git(args, repository.path, 'deleteRef')
50
- }
package/src/git/var.ts DELETED
@@ -1,42 +0,0 @@
1
- import { git } from './core.js'
2
- import { Repository } from '../models/repository.js'
3
- import { CommitIdentity } from '../models/commit-identity.js'
4
-
5
- /**
6
- * Gets the author identity, ie the name and email which would
7
- * have been used should a commit have been performed in this
8
- * instance. This differs from what's stored in the user.name
9
- * and user.email config variables in that it will match what
10
- * Git itself will use in a commit even if there's no name or
11
- * email configured. If no email or name is configured Git will
12
- * attempt to come up with a suitable replacement using the
13
- * signed-in system user and hostname.
14
- *
15
- * A null return value means that no name/and or email was set
16
- * and the user.useconfigonly setting prevented Git from making
17
- * up a user ident string. If this returns null any subsequent
18
- * commits can be expected to fail as well.
19
- */
20
- export async function getAuthorIdentity(
21
- repository: Repository
22
- ): Promise<CommitIdentity | null> {
23
- const result = await git(
24
- ['var', 'GIT_AUTHOR_IDENT'],
25
- repository.path,
26
- 'getAuthorIdentity',
27
- {
28
- successExitCodes: new Set([0, 128]),
29
- }
30
- )
31
-
32
- // If user.user.useconfigonly is set and no user.name or user.email
33
- if (result.exitCode === 128) {
34
- return null
35
- }
36
-
37
- try {
38
- return CommitIdentity.parseIdentity(result.stdout)
39
- } catch (err) {
40
- return null
41
- }
42
- }
@@ -1,146 +0,0 @@
1
- import * as Fs from 'fs'
2
- import * as Path from 'path'
3
- import { readFile, copyFile, mkdir } from 'fs/promises'
4
- import ignore from 'ignore'
5
- import type { Repository } from '../models/repository.js'
6
- import { git } from './core.js'
7
- import { addWorktree, getMainWorktreePath } from './worktree.js'
8
-
9
- const WorktreeIncludeFile = '.worktreeinclude'
10
-
11
- /**
12
- * Reads the patterns from the `.worktreeinclude` file at the root of the
13
- * given repository path.
14
- *
15
- * The file uses `.gitignore` syntax. Blank lines and lines starting with `#`
16
- * are ignored.
17
- *
18
- * Returns an empty array if the file does not exist.
19
- */
20
- export async function readWorktreeIncludePatterns(
21
- repositoryPath: string
22
- ): Promise<ReadonlyArray<string>> {
23
- const filePath = Path.join(repositoryPath, WorktreeIncludeFile)
24
-
25
- let contents: string
26
- try {
27
- contents = await readFile(filePath, 'utf8')
28
- } catch {
29
- return []
30
- }
31
-
32
- return contents
33
- .split('\n')
34
- .map(line => line.trim())
35
- .filter(line => line.length > 0 && !line.startsWith('#'))
36
- }
37
-
38
- /**
39
- * Returns the list of gitignored files in `repositoryPath` that match any of
40
- * the given patterns.
41
- *
42
- * Only files that are both gitignored **and** matched by a `.worktreeinclude`
43
- * pattern are returned — tracked files are never included.
44
- */
45
- export async function getIgnoredFilesMatchingPatterns(
46
- repository: Repository,
47
- patterns: ReadonlyArray<string>
48
- ): Promise<ReadonlyArray<string>> {
49
- if (patterns.length === 0) {
50
- return []
51
- }
52
-
53
- const result = await git(
54
- ['ls-files', '--others', '--ignored', '--exclude-standard', '-z'],
55
- repository.path,
56
- 'getIgnoredFiles'
57
- )
58
-
59
- // Files are NUL-separated; filter out empty entries from the split
60
- const ignoredFiles = result.stdout.split('\0').filter(f => f.length > 0)
61
-
62
- const ig = ignore().add(patterns)
63
- return ignoredFiles.filter(f => ig.ignores(f))
64
- }
65
-
66
- /**
67
- * Copies each file in `files` (relative paths) from `sourcePath` to
68
- * `destinationPath`, preserving the directory structure.
69
- *
70
- * Files that cannot be copied (e.g. because they no longer exist at the
71
- * source) are skipped silently — a failure to copy a single file never
72
- * prevents the others from being copied.
73
- */
74
- export async function copyWorktreeIncludeFiles(
75
- sourcePath: string,
76
- destinationPath: string,
77
- files: ReadonlyArray<string>
78
- ): Promise<void> {
79
- for (const file of files) {
80
- const src = Path.join(sourcePath, file)
81
- const dest = Path.join(destinationPath, file)
82
-
83
- // Guard against path traversal: the resolved destination must be
84
- // inside the worktree directory.
85
- const resolvedDest = Path.resolve(dest)
86
- const resolvedWorktreeRoot = Path.resolve(destinationPath)
87
- if (!resolvedDest.startsWith(resolvedWorktreeRoot + Path.sep)) {
88
- continue
89
- }
90
-
91
- try {
92
- // eslint-disable-next-line no-sync
93
- if (!Fs.existsSync(src)) {
94
- continue
95
- }
96
-
97
- await mkdir(Path.dirname(dest), { recursive: true })
98
- await copyFile(src, dest)
99
- } catch (e) {
100
- console.warn(
101
- `[worktree-include] Failed to copy '${file}' to worktree`,
102
- e instanceof Error ? e : undefined
103
- )
104
- }
105
- }
106
- }
107
-
108
- /**
109
- * Creates a new git worktree and then copies any gitignored files listed in
110
- * the `.worktreeinclude` file from the main worktree into the newly created
111
- * worktree.
112
- *
113
- * The copy step is best-effort: failures are logged but do not prevent the
114
- * worktree from being used.
115
- *
116
- * @param repository The repository to create the worktree in.
117
- * @param path The absolute path where the new worktree should be created.
118
- * @param options Options forwarded to `addWorktree`.
119
- */
120
- export async function addWorktreeWithIncludes(
121
- repository: Repository,
122
- path: string,
123
- options: Parameters<typeof addWorktree>[2] = {}
124
- ): Promise<void> {
125
- await addWorktree(repository, path, options)
126
-
127
- try {
128
- const mainPath = (await getMainWorktreePath(repository)) ?? repository.path
129
- const patterns = await readWorktreeIncludePatterns(mainPath)
130
-
131
- if (patterns.length === 0) {
132
- return
133
- }
134
-
135
- const files = await getIgnoredFilesMatchingPatterns(repository, patterns)
136
-
137
- if (files.length > 0) {
138
- await copyWorktreeIncludeFiles(mainPath, path, files)
139
- }
140
- } catch (e) {
141
- console.warn(
142
- '[worktree-include] Failed to process .worktreeinclude; worktree was still created',
143
- e instanceof Error ? e : undefined
144
- )
145
- }
146
- }