@gitkraken/core-gitlens 0.1.0 → 0.2.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.
- package/CHANGELOG.md +22 -1
- package/dist/git/cache.d.ts +21 -5
- package/dist/git/cache.d.ts.map +1 -1
- package/dist/git/cache.js +102 -6
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +11 -2
- package/dist/git/context.d.ts.map +1 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/models/branch.d.ts +1 -0
- package/dist/git/models/branch.d.ts.map +1 -1
- package/dist/git/models/branch.js.map +1 -1
- package/dist/git/models/commit.d.ts +1 -9
- package/dist/git/models/commit.d.ts.map +1 -1
- package/dist/git/models/commit.js +4 -9
- package/dist/git/models/commit.js.map +1 -1
- package/dist/git/models/graph.d.ts +2 -4
- package/dist/git/models/graph.d.ts.map +1 -1
- package/dist/git/models/repository.d.ts +12 -3
- package/dist/git/models/repository.d.ts.map +1 -1
- package/dist/git/models/repository.js +25 -4
- package/dist/git/models/repository.js.map +1 -1
- package/dist/git/models/worktree.d.ts +1 -1
- package/dist/git/models/worktree.d.ts.map +1 -1
- package/dist/git/models/worktree.js +2 -2
- package/dist/git/models/worktree.js.map +1 -1
- package/dist/git/parsers/diffParser.d.ts +0 -1
- package/dist/git/parsers/diffParser.d.ts.map +1 -1
- package/dist/git/parsers/diffParser.js +22 -61
- package/dist/git/parsers/diffParser.js.map +1 -1
- package/dist/git/providers/branches.d.ts +3 -0
- package/dist/git/providers/branches.d.ts.map +1 -1
- package/dist/git/providers/commits.d.ts +6 -0
- package/dist/git/providers/commits.d.ts.map +1 -1
- package/dist/git/providers/config.d.ts +2 -0
- package/dist/git/providers/config.d.ts.map +1 -1
- package/dist/git/providers/diff.d.ts +2 -0
- package/dist/git/providers/diff.d.ts.map +1 -1
- package/dist/git/providers/operations.d.ts +6 -0
- package/dist/git/providers/operations.d.ts.map +1 -1
- package/dist/git/providers/revision.d.ts +1 -1
- package/dist/git/providers/revision.d.ts.map +1 -1
- package/dist/git/providers/staging.d.ts +2 -0
- package/dist/git/providers/staging.d.ts.map +1 -1
- package/dist/git/utils/sorting.d.ts +6 -0
- package/dist/git/utils/sorting.d.ts.map +1 -1
- package/dist/git/utils/sorting.js +19 -0
- package/dist/git/utils/sorting.js.map +1 -1
- package/dist/git-cli/cliGitProvider.js +1 -1
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +29 -4
- package/dist/git-cli/exec/git.d.ts.map +1 -1
- package/dist/git-cli/exec/git.js +70 -9
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/gitQueue.d.ts +12 -4
- package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
- package/dist/git-cli/exec/gitQueue.js +49 -12
- package/dist/git-cli/exec/gitQueue.js.map +1 -1
- package/dist/git-cli/parsers/logParser.d.ts +1 -0
- package/dist/git-cli/parsers/logParser.d.ts.map +1 -1
- package/dist/git-cli/parsers/logParser.js +4 -0
- package/dist/git-cli/parsers/logParser.js.map +1 -1
- package/dist/git-cli/providers/blame.js +1 -1
- package/dist/git-cli/providers/blame.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +2 -0
- package/dist/git-cli/providers/branches.d.ts.map +1 -1
- package/dist/git-cli/providers/branches.js +176 -123
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +4 -0
- package/dist/git-cli/providers/commits.d.ts.map +1 -1
- package/dist/git-cli/providers/commits.js +58 -17
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts.map +1 -1
- package/dist/git-cli/providers/config.js +9 -9
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/contributors.d.ts.map +1 -1
- package/dist/git-cli/providers/contributors.js +7 -4
- package/dist/git-cli/providers/contributors.js.map +1 -1
- package/dist/git-cli/providers/diff.d.ts +2 -0
- package/dist/git-cli/providers/diff.d.ts.map +1 -1
- package/dist/git-cli/providers/diff.js +89 -19
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/graph.d.ts.map +1 -1
- package/dist/git-cli/providers/graph.js +43 -27
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +17 -0
- package/dist/git-cli/providers/operations.d.ts.map +1 -1
- package/dist/git-cli/providers/operations.js +47 -14
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/patch.d.ts.map +1 -1
- package/dist/git-cli/providers/patch.js +15 -30
- package/dist/git-cli/providers/patch.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +6 -6
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts.map +1 -1
- package/dist/git-cli/providers/refs.js +26 -7
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/remotes.js +4 -4
- package/dist/git-cli/providers/remotes.js.map +1 -1
- package/dist/git-cli/providers/revision.d.ts +1 -1
- package/dist/git-cli/providers/revision.d.ts.map +1 -1
- package/dist/git-cli/providers/revision.js +15 -11
- package/dist/git-cli/providers/revision.js.map +1 -1
- package/dist/git-cli/providers/staging.d.ts +2 -0
- package/dist/git-cli/providers/staging.d.ts.map +1 -1
- package/dist/git-cli/providers/staging.js +20 -8
- package/dist/git-cli/providers/staging.js.map +1 -1
- package/dist/git-cli/providers/stash.d.ts +0 -8
- package/dist/git-cli/providers/stash.d.ts.map +1 -1
- package/dist/git-cli/providers/stash.js +63 -119
- package/dist/git-cli/providers/stash.js.map +1 -1
- package/dist/git-cli/providers/status.js +6 -6
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/git-cli/providers/tags.js +4 -4
- package/dist/git-cli/providers/tags.js.map +1 -1
- package/dist/git-cli/providers/worktrees.js +3 -3
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/plus/ai/constants.d.ts +2 -1
- package/dist/plus/ai/constants.d.ts.map +1 -1
- package/dist/plus/ai/constants.js +7 -0
- package/dist/plus/ai/constants.js.map +1 -1
- package/dist/plus/ai/models/model.d.ts +1 -1
- package/dist/plus/ai/models/model.d.ts.map +1 -1
- package/dist/plus/ai/models/model.js.map +1 -1
- package/dist/plus/ai/models/promptTemplates.d.ts +19 -2
- package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
- package/dist/plus/ai/models/results.d.ts +28 -0
- package/dist/plus/ai/models/results.d.ts.map +1 -1
- package/dist/plus/ai/prompts.d.ts +3 -0
- package/dist/plus/ai/prompts.d.ts.map +1 -1
- package/dist/plus/ai/prompts.js +126 -0
- package/dist/plus/ai/prompts.js.map +1 -1
- package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/ai.utils.js +2 -0
- package/dist/plus/ai/utils/ai.utils.js.map +1 -1
- package/dist/plus/ai/utils/results.utils.d.ts +3 -0
- package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/results.utils.js +75 -0
- package/dist/plus/ai/utils/results.utils.js.map +1 -1
- package/dist/plus/ai/utils/truncation.utils.d.ts +1 -1
- package/dist/plus/ai/utils/truncation.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/truncation.utils.js.map +1 -1
- package/dist/plus/git-github/providers/github/branches.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/branches.js +16 -1
- package/dist/plus/git-github/providers/github/branches.js.map +1 -1
- package/dist/plus/git-github/providers/github/diff.d.ts +2 -0
- package/dist/plus/git-github/providers/github/diff.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/diff.js.map +1 -1
- package/dist/utils/decorators/log.js +1 -1
- package/dist/utils/decorators/log.js.map +1 -1
- package/dist/utils/decorators/sequentialize.d.ts.map +1 -1
- package/dist/utils/decorators/sequentialize.js +4 -2
- package/dist/utils/decorators/sequentialize.js.map +1 -1
- package/dist/utils/env/node/base64.js.map +1 -1
- package/dist/utils/env/node/exec.js.map +1 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +4 -10
- package/dist/utils/formatter.js.map +1 -1
- package/dist/utils/iterable.js.map +1 -1
- package/dist/utils/lruMap.d.ts +40 -0
- package/dist/utils/lruMap.d.ts.map +1 -0
- package/dist/utils/lruMap.js +81 -0
- package/dist/utils/lruMap.js.map +1 -0
- package/dist/utils/version.d.ts +14 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +48 -0
- package/dist/utils/version.js.map +1 -1
- package/package.json +1 -1
- package/src/git/cache.ts +179 -13
- package/src/git/context.ts +11 -2
- package/src/git/models/branch.ts +1 -0
- package/src/git/models/commit.ts +1 -17
- package/src/git/models/graph.ts +2 -4
- package/src/git/models/repository.ts +26 -6
- package/src/git/models/worktree.ts +2 -2
- package/src/git/parsers/diffParser.ts +7 -44
- package/src/git/providers/branches.ts +3 -0
- package/src/git/providers/commits.ts +7 -0
- package/src/git/providers/config.ts +2 -0
- package/src/git/providers/diff.ts +8 -2
- package/src/git/providers/operations.ts +10 -3
- package/src/git/providers/revision.ts +5 -1
- package/src/git/providers/staging.ts +2 -0
- package/src/git/utils/sorting.ts +21 -0
- package/src/git-cli/cliGitProvider.ts +1 -1
- package/src/git-cli/exec/git.ts +70 -18
- package/src/git-cli/exec/gitQueue.ts +57 -13
- package/src/git-cli/parsers/logParser.ts +5 -1
- package/src/git-cli/providers/blame.ts +1 -1
- package/src/git-cli/providers/branches.ts +207 -133
- package/src/git-cli/providers/commits.ts +71 -18
- package/src/git-cli/providers/config.ts +9 -14
- package/src/git-cli/providers/contributors.ts +7 -12
- package/src/git-cli/providers/diff.ts +100 -19
- package/src/git-cli/providers/graph.ts +47 -27
- package/src/git-cli/providers/operations.ts +77 -18
- package/src/git-cli/providers/patch.ts +15 -37
- package/src/git-cli/providers/pausedOperations.ts +6 -6
- package/src/git-cli/providers/refs.ts +27 -8
- package/src/git-cli/providers/remotes.ts +4 -4
- package/src/git-cli/providers/revision.ts +20 -13
- package/src/git-cli/providers/staging.ts +18 -8
- package/src/git-cli/providers/stash.ts +67 -134
- package/src/git-cli/providers/status.ts +6 -6
- package/src/git-cli/providers/tags.ts +4 -4
- package/src/git-cli/providers/worktrees.ts +3 -3
- package/src/plus/ai/constants.ts +8 -0
- package/src/plus/ai/models/model.ts +1 -0
- package/src/plus/ai/models/promptTemplates.ts +29 -0
- package/src/plus/ai/models/results.ts +30 -0
- package/src/plus/ai/prompts.ts +129 -0
- package/src/plus/ai/utils/ai.utils.ts +2 -0
- package/src/plus/ai/utils/results.utils.ts +99 -0
- package/src/plus/ai/utils/truncation.utils.ts +3 -1
- package/src/plus/git-github/providers/github/branches.ts +17 -5
- package/src/plus/git-github/providers/github/diff.ts +8 -2
- package/src/utils/decorators/log.ts +1 -1
- package/src/utils/decorators/sequentialize.ts +8 -6
- package/src/utils/env/node/base64.ts +1 -1
- package/src/utils/env/node/exec.ts +2 -2
- package/src/utils/formatter.ts +4 -11
- package/src/utils/iterable.ts +1 -1
- package/src/utils/lruMap.ts +87 -0
- package/src/utils/version.ts +48 -0
package/src/git/cache.ts
CHANGED
|
@@ -8,10 +8,12 @@ import type { PromiseOrValue } from '../utils/promise.js';
|
|
|
8
8
|
import type { CacheController } from '../utils/promiseCache.js';
|
|
9
9
|
import { PromiseCache, PromiseMap, RepoPromiseCacheMap } from '../utils/promiseCache.js';
|
|
10
10
|
import type { Uri } from '../utils/uri.js';
|
|
11
|
+
import { getBranchId } from './utils/branch.utils.js';
|
|
12
|
+
import { createReference } from './utils/reference.utils.js';
|
|
11
13
|
import { getCommonRepositoryPath, getRepositoryOrWorktreePath } from './utils/repository.utils.js';
|
|
12
14
|
import type { GitResult } from './exec.types.js';
|
|
13
15
|
import type { ProgressiveGitBlame } from './models/blame.js';
|
|
14
|
-
import type { GitBranch } from './models/branch.js';
|
|
16
|
+
import type { BranchMetadata, GitBranch } from './models/branch.js';
|
|
15
17
|
import type { GitStashCommit } from './models/commit.js';
|
|
16
18
|
import type { GitContributor, GitContributorsStats } from './models/contributor.js';
|
|
17
19
|
import type { ParsedGitDiffHunks } from './models/diff.js';
|
|
@@ -26,6 +28,7 @@ import type { GitStash } from './models/stash.js';
|
|
|
26
28
|
import type { GitTag } from './models/tag.js';
|
|
27
29
|
import type { GitUser } from './models/user.js';
|
|
28
30
|
import type { GitWorktree } from './models/worktree.js';
|
|
31
|
+
import type { BranchContributionsOverview, GitBranchMergedStatus } from './providers/branches.js';
|
|
29
32
|
import type { GitCommitReachability, LeftRightCommitCountResult } from './providers/commits.js';
|
|
30
33
|
import type { GitContributorsResult } from './providers/contributors.js';
|
|
31
34
|
import type { ResolvedRevision } from './providers/revision.js';
|
|
@@ -49,6 +52,7 @@ export type CachedGitTypes =
|
|
|
49
52
|
| 'contributors'
|
|
50
53
|
| 'gitignore'
|
|
51
54
|
| 'gkConfig'
|
|
55
|
+
| 'lastFetched'
|
|
52
56
|
| 'providers'
|
|
53
57
|
| 'remotes'
|
|
54
58
|
| 'stashes'
|
|
@@ -59,6 +63,12 @@ export type CachedGitTypes =
|
|
|
59
63
|
|
|
60
64
|
export type ConflictDetectionCacheKey = `apply:${string}:${string}:${string}` | `merge:${string}:${string}`;
|
|
61
65
|
|
|
66
|
+
/**
|
|
67
|
+
* gkConfig keys that participate in the `branchOverviews` cache's mergeTarget/mergeBase lineage.
|
|
68
|
+
* Capture group 1 is the ref name (which may itself contain `.`/`/`).
|
|
69
|
+
*/
|
|
70
|
+
const branchOverviewGkConfigKeyPattern = /^branch\.(.+)\.(?:gk-merge-(?:base|target(?:-user)?)|gk-target-base)$/;
|
|
71
|
+
|
|
62
72
|
/** Per-worktree caches — cleared by repoPath directly */
|
|
63
73
|
interface Caches {
|
|
64
74
|
bestRemotes: PromiseMap<RepoPath, GitRemote<RemoteProvider>[]> | undefined;
|
|
@@ -83,6 +93,10 @@ interface Caches {
|
|
|
83
93
|
|
|
84
94
|
/** Shared caches — cleared via commonPath + all worktree paths */
|
|
85
95
|
interface SharedCaches {
|
|
96
|
+
baseBranchName: RepoPromiseCacheMap<string, string | undefined> | undefined;
|
|
97
|
+
branchMergedStatus: RepoPromiseCacheMap<string, GitBranchMergedStatus> | undefined;
|
|
98
|
+
branchMetadataMap: PromiseMap<RepoPath, Map<string, BranchMetadata>> | undefined;
|
|
99
|
+
branchOverviews: RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> | undefined;
|
|
86
100
|
branches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;
|
|
87
101
|
configKeys: RepoPromiseCacheMap<string, string | undefined> | undefined;
|
|
88
102
|
configPatterns: RepoPromiseCacheMap<string, Map<string, string>> | undefined;
|
|
@@ -97,7 +111,7 @@ interface SharedCaches {
|
|
|
97
111
|
logShas: RepoPromiseCacheMap<string, string[]> | undefined;
|
|
98
112
|
remotes: PromiseMap<RepoPath, GitRemote[]> | undefined;
|
|
99
113
|
sharedBranches: PromiseMap<RepoPath, PagedResult<GitBranch>> | undefined;
|
|
100
|
-
stashes:
|
|
114
|
+
stashes: RepoPromiseCacheMap<string, GitStash> | undefined;
|
|
101
115
|
tags: PromiseMap<RepoPath, PagedResult<GitTag>> | undefined;
|
|
102
116
|
worktrees: PromiseMap<RepoPath, GitWorktree[]> | undefined;
|
|
103
117
|
}
|
|
@@ -107,6 +121,10 @@ type AllCaches = Caches & SharedCaches;
|
|
|
107
121
|
/** Compile-time enforced: adding a key to SharedCaches without listing it here is a type error */
|
|
108
122
|
const sharedCacheKeys: ReadonlySet<keyof AllCaches> = new Set(
|
|
109
123
|
exhaustiveArray<keyof SharedCaches>()([
|
|
124
|
+
'baseBranchName',
|
|
125
|
+
'branchMergedStatus',
|
|
126
|
+
'branchMetadataMap',
|
|
127
|
+
'branchOverviews',
|
|
110
128
|
'branches',
|
|
111
129
|
'configKeys',
|
|
112
130
|
'configPatterns',
|
|
@@ -129,9 +147,13 @@ const sharedCacheKeys: ReadonlySet<keyof AllCaches> = new Set(
|
|
|
129
147
|
|
|
130
148
|
function createEmptyCaches(): AllCaches {
|
|
131
149
|
return {
|
|
150
|
+
baseBranchName: undefined,
|
|
132
151
|
bestRemotes: undefined,
|
|
133
152
|
blame: undefined,
|
|
134
153
|
branch: undefined,
|
|
154
|
+
branchMergedStatus: undefined,
|
|
155
|
+
branchMetadataMap: undefined,
|
|
156
|
+
branchOverviews: undefined,
|
|
135
157
|
branches: undefined,
|
|
136
158
|
fileExistence: undefined,
|
|
137
159
|
ignoreRevsFile: undefined,
|
|
@@ -206,10 +228,33 @@ export class Cache implements Disposable {
|
|
|
206
228
|
}));
|
|
207
229
|
}
|
|
208
230
|
|
|
231
|
+
private get baseBranchName(): RepoPromiseCacheMap<string, string | undefined> {
|
|
232
|
+
return (this._caches.baseBranchName ??= new RepoPromiseCacheMap<string, string | undefined>());
|
|
233
|
+
}
|
|
234
|
+
|
|
209
235
|
get branch(): PromiseMap<RepoPath, GitBranch | undefined> {
|
|
210
236
|
return (this._caches.branch ??= new PromiseMap<RepoPath, GitBranch | undefined>());
|
|
211
237
|
}
|
|
212
238
|
|
|
239
|
+
get branchMergedStatus(): RepoPromiseCacheMap<string, GitBranchMergedStatus> {
|
|
240
|
+
return (this._caches.branchMergedStatus ??= new RepoPromiseCacheMap<string, GitBranchMergedStatus>({
|
|
241
|
+
createTTL: 1000 * 60 * 5, // 5 minutes
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private get branchMetadataMap(): PromiseMap<RepoPath, Map<string, BranchMetadata>> {
|
|
246
|
+
return (this._caches.branchMetadataMap ??= new PromiseMap<RepoPath, Map<string, BranchMetadata>>());
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private get branchOverviews(): RepoPromiseCacheMap<string, BranchContributionsOverview | undefined> {
|
|
250
|
+
return (this._caches.branchOverviews ??= new RepoPromiseCacheMap<
|
|
251
|
+
string,
|
|
252
|
+
BranchContributionsOverview | undefined
|
|
253
|
+
>(
|
|
254
|
+
{ accessTTL: 1000 * 60 * 60 }, // 60 minutes
|
|
255
|
+
));
|
|
256
|
+
}
|
|
257
|
+
|
|
213
258
|
get branches(): PromiseMap<RepoPath, PagedResult<GitBranch>> {
|
|
214
259
|
return (this._caches.branches ??= new PromiseMap<RepoPath, PagedResult<GitBranch>>());
|
|
215
260
|
}
|
|
@@ -364,8 +409,10 @@ export class Cache implements Disposable {
|
|
|
364
409
|
return (this._caches.remotes ??= new PromiseMap<RepoPath, GitRemote[]>());
|
|
365
410
|
}
|
|
366
411
|
|
|
367
|
-
get stashes():
|
|
368
|
-
return (this._caches.stashes ??= new
|
|
412
|
+
get stashes(): RepoPromiseCacheMap<string, GitStash> {
|
|
413
|
+
return (this._caches.stashes ??= new RepoPromiseCacheMap<string, GitStash>({
|
|
414
|
+
accessTTL: 1000 * 60 * 60, // 60 minutes
|
|
415
|
+
}));
|
|
369
416
|
}
|
|
370
417
|
|
|
371
418
|
get tags(): PromiseMap<RepoPath, PagedResult<GitTag>> {
|
|
@@ -424,9 +471,14 @@ export class Cache implements Disposable {
|
|
|
424
471
|
keysToClear.add('fileLog');
|
|
425
472
|
}
|
|
426
473
|
|
|
427
|
-
//
|
|
474
|
+
// Branch caches affected by HEAD/heads changes — `branchMergedStatus` is shared
|
|
475
|
+
// (the answer is invariant across worktrees of the same common repo) but is invalidated
|
|
476
|
+
// here because branch-tip movement in any worktree can change the merge status; the
|
|
477
|
+
// shared-clear logic below routes shared keys via commonPath.
|
|
428
478
|
if (types.includes('branch') || types.includes('branches')) {
|
|
429
479
|
keysToClear.add('branch');
|
|
480
|
+
keysToClear.add('branchMergedStatus');
|
|
481
|
+
keysToClear.add('branchOverviews');
|
|
430
482
|
keysToClear.add('conflictDetection');
|
|
431
483
|
keysToClear.add('currentBranchReference');
|
|
432
484
|
keysToClear.add('leftRightCommitCount');
|
|
@@ -436,6 +488,8 @@ export class Cache implements Disposable {
|
|
|
436
488
|
|
|
437
489
|
// Shared branch caches (branch list, metadata)
|
|
438
490
|
if (types.includes('branches')) {
|
|
491
|
+
keysToClear.add('baseBranchName');
|
|
492
|
+
keysToClear.add('branchMetadataMap');
|
|
439
493
|
keysToClear.add('branches');
|
|
440
494
|
keysToClear.add('sharedBranches');
|
|
441
495
|
keysToClear.add('defaultBranchName');
|
|
@@ -452,6 +506,7 @@ export class Cache implements Disposable {
|
|
|
452
506
|
}
|
|
453
507
|
|
|
454
508
|
if (types.includes('contributors')) {
|
|
509
|
+
keysToClear.add('branchOverviews');
|
|
455
510
|
keysToClear.add('contributors');
|
|
456
511
|
keysToClear.add('contributorsLite');
|
|
457
512
|
keysToClear.add('contributorsStats');
|
|
@@ -464,6 +519,16 @@ export class Cache implements Disposable {
|
|
|
464
519
|
if (types.includes('gkConfig')) {
|
|
465
520
|
keysToClear.add('gkConfigKeys');
|
|
466
521
|
keysToClear.add('gkConfigPatterns');
|
|
522
|
+
// Derived from `branch.<ref>.gk-merge-base`/`vscode-merge-base`; clear so external
|
|
523
|
+
// gkConfig mutations don't leave stale base-branch resolutions cached.
|
|
524
|
+
keysToClear.add('baseBranchName');
|
|
525
|
+
// Cached overviews use Tier 1's stored merge target as their key-stability anchor;
|
|
526
|
+
// stored-target changes must invalidate or readers see stale `mergeTarget`/stats.
|
|
527
|
+
keysToClear.add('branchOverviews');
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (types.includes('lastFetched')) {
|
|
531
|
+
keysToClear.add('lastFetched');
|
|
467
532
|
}
|
|
468
533
|
|
|
469
534
|
if (types.includes('providers')) {
|
|
@@ -700,6 +765,10 @@ export class Cache implements Disposable {
|
|
|
700
765
|
types.add('gkConfig');
|
|
701
766
|
}
|
|
702
767
|
|
|
768
|
+
if (hasAny('lastFetched')) {
|
|
769
|
+
types.add('lastFetched');
|
|
770
|
+
}
|
|
771
|
+
|
|
703
772
|
if (hasAny('remoteProviders')) {
|
|
704
773
|
types.add('providers');
|
|
705
774
|
}
|
|
@@ -859,6 +928,42 @@ export class Cache implements Disposable {
|
|
|
859
928
|
const cacheKey = this.getCommonPath(repoPath);
|
|
860
929
|
this._caches.gkConfigKeys?.delete(cacheKey, key);
|
|
861
930
|
this._caches.gkConfigPatterns?.delete(cacheKey);
|
|
931
|
+
|
|
932
|
+
// When the change affects a branch's merge-target/base lineage, invalidate that branch's
|
|
933
|
+
// cached overview so subsequent reads pick up the new stored value rather than stale data.
|
|
934
|
+
// `getBranchContributionsOverview` keys `branchOverviews` by ref, with Tier 1's stored
|
|
935
|
+
// target as the key-stability anchor — so any write to those keys must invalidate.
|
|
936
|
+
const refMatch = key.match(branchOverviewGkConfigKeyPattern);
|
|
937
|
+
if (refMatch != null) {
|
|
938
|
+
this._caches.branchOverviews?.delete(cacheKey, refMatch[1]);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
async getBranchOverview(
|
|
943
|
+
repoPath: string,
|
|
944
|
+
cacheKey: string,
|
|
945
|
+
factory: (
|
|
946
|
+
commonPath: string,
|
|
947
|
+
cacheable: CacheController,
|
|
948
|
+
cancellation?: AbortSignal,
|
|
949
|
+
) => PromiseOrValue<BranchContributionsOverview | undefined>,
|
|
950
|
+
options?: { accessTTL?: number; cancellation?: AbortSignal },
|
|
951
|
+
): Promise<BranchContributionsOverview | undefined> {
|
|
952
|
+
return this.getSharedOrCreateWithKey(
|
|
953
|
+
this.branchOverviews,
|
|
954
|
+
repoPath,
|
|
955
|
+
cacheKey,
|
|
956
|
+
factory,
|
|
957
|
+
(data, newRepoPath) =>
|
|
958
|
+
data == null
|
|
959
|
+
? data
|
|
960
|
+
: {
|
|
961
|
+
...data,
|
|
962
|
+
repoPath: newRepoPath,
|
|
963
|
+
contributors: data.contributors.map(c => c.withRepoPath(newRepoPath)),
|
|
964
|
+
},
|
|
965
|
+
options,
|
|
966
|
+
);
|
|
862
967
|
}
|
|
863
968
|
|
|
864
969
|
async getContributors(
|
|
@@ -907,12 +1012,66 @@ export class Cache implements Disposable {
|
|
|
907
1012
|
getContributorsStats(
|
|
908
1013
|
repoPath: string,
|
|
909
1014
|
cacheKey: string,
|
|
910
|
-
factory: (commonPath: string) => PromiseOrValue<GitContributorsStats | undefined>,
|
|
911
|
-
options?: { accessTTL?: number },
|
|
1015
|
+
factory: (commonPath: string, cancellation?: AbortSignal) => PromiseOrValue<GitContributorsStats | undefined>,
|
|
1016
|
+
options?: { accessTTL?: number; cancellation?: AbortSignal },
|
|
912
1017
|
): Promise<GitContributorsStats | undefined> {
|
|
913
1018
|
return this.getSharedSimpleWithKey(this.contributorsStats, repoPath, cacheKey, factory, options);
|
|
914
1019
|
}
|
|
915
1020
|
|
|
1021
|
+
getBaseBranchName(
|
|
1022
|
+
repoPath: string,
|
|
1023
|
+
ref: string,
|
|
1024
|
+
factory: (commonPath: string, cancellation?: AbortSignal) => PromiseOrValue<string | undefined>,
|
|
1025
|
+
cancellation?: AbortSignal,
|
|
1026
|
+
): Promise<string | undefined> {
|
|
1027
|
+
return this.getSharedSimpleWithKey(this.baseBranchName, repoPath, ref, factory, {
|
|
1028
|
+
cancellation: cancellation,
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
getBranchMergedStatus(
|
|
1033
|
+
repoPath: string,
|
|
1034
|
+
cacheKey: string,
|
|
1035
|
+
factory: (
|
|
1036
|
+
commonPath: string,
|
|
1037
|
+
cacheable: CacheController,
|
|
1038
|
+
cancellation?: AbortSignal,
|
|
1039
|
+
) => PromiseOrValue<GitBranchMergedStatus>,
|
|
1040
|
+
cancellation?: AbortSignal,
|
|
1041
|
+
): Promise<GitBranchMergedStatus> {
|
|
1042
|
+
return this.getSharedOrCreateWithKey(
|
|
1043
|
+
this.branchMergedStatus,
|
|
1044
|
+
repoPath,
|
|
1045
|
+
cacheKey,
|
|
1046
|
+
factory,
|
|
1047
|
+
(data, newRepoPath) => {
|
|
1048
|
+
if (!data.merged) return data;
|
|
1049
|
+
if (data.localBranchOnly == null) return data;
|
|
1050
|
+
|
|
1051
|
+
const lbo = data.localBranchOnly;
|
|
1052
|
+
return {
|
|
1053
|
+
...data,
|
|
1054
|
+
localBranchOnly: createReference(lbo.ref, newRepoPath, {
|
|
1055
|
+
id: getBranchId(newRepoPath, lbo.remote, lbo.name),
|
|
1056
|
+
refType: 'branch',
|
|
1057
|
+
name: lbo.name,
|
|
1058
|
+
remote: lbo.remote,
|
|
1059
|
+
upstream: lbo.upstream,
|
|
1060
|
+
sha: lbo.sha,
|
|
1061
|
+
}),
|
|
1062
|
+
};
|
|
1063
|
+
},
|
|
1064
|
+
{ cancellation: cancellation },
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
getBranchMetadataMap(
|
|
1069
|
+
repoPath: string,
|
|
1070
|
+
factory: (commonPath: string) => PromiseOrValue<Map<string, BranchMetadata>>,
|
|
1071
|
+
): Promise<Map<string, BranchMetadata>> {
|
|
1072
|
+
return this.getSharedSimple(this.branchMetadataMap, repoPath, factory);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
916
1075
|
getDefaultBranchName(
|
|
917
1076
|
repoPath: string,
|
|
918
1077
|
remote: string,
|
|
@@ -955,16 +1114,18 @@ export class Cache implements Disposable {
|
|
|
955
1114
|
|
|
956
1115
|
async getStash(
|
|
957
1116
|
repoPath: string,
|
|
1117
|
+
cacheKey: string,
|
|
958
1118
|
factory: (
|
|
959
1119
|
commonPath: string,
|
|
960
1120
|
cacheable: CacheController,
|
|
961
1121
|
cancellation?: AbortSignal,
|
|
962
1122
|
) => PromiseOrValue<GitStash>,
|
|
963
|
-
cancellation?: AbortSignal,
|
|
1123
|
+
options?: { accessTTL?: number; cancellation?: AbortSignal },
|
|
964
1124
|
): Promise<GitStash> {
|
|
965
|
-
return this.
|
|
1125
|
+
return this.getSharedOrCreateWithKey(
|
|
966
1126
|
this.stashes,
|
|
967
1127
|
repoPath,
|
|
1128
|
+
cacheKey,
|
|
968
1129
|
factory,
|
|
969
1130
|
(data, newRepoPath) => ({
|
|
970
1131
|
repoPath: newRepoPath,
|
|
@@ -975,7 +1136,7 @@ export class Cache implements Disposable {
|
|
|
975
1136
|
]),
|
|
976
1137
|
),
|
|
977
1138
|
}),
|
|
978
|
-
|
|
1139
|
+
options,
|
|
979
1140
|
);
|
|
980
1141
|
}
|
|
981
1142
|
|
|
@@ -1142,11 +1303,16 @@ export class Cache implements Disposable {
|
|
|
1142
1303
|
cache: RepoPromiseCacheMap<string, T>,
|
|
1143
1304
|
repoPath: string,
|
|
1144
1305
|
cacheKey: string,
|
|
1145
|
-
factory: (commonPath: string) => PromiseOrValue<T>,
|
|
1146
|
-
options?: { accessTTL?: number },
|
|
1306
|
+
factory: (commonPath: string, cancellation?: AbortSignal) => PromiseOrValue<T>,
|
|
1307
|
+
options?: { accessTTL?: number; cancellation?: AbortSignal },
|
|
1147
1308
|
): Promise<T> {
|
|
1148
1309
|
const commonPath = this.getCommonPath(repoPath);
|
|
1149
1310
|
|
|
1150
|
-
return cache.getOrCreate(
|
|
1311
|
+
return cache.getOrCreate(
|
|
1312
|
+
commonPath,
|
|
1313
|
+
cacheKey,
|
|
1314
|
+
(_cacheable, signal) => Promise.resolve(factory(commonPath, signal)),
|
|
1315
|
+
options,
|
|
1316
|
+
);
|
|
1151
1317
|
}
|
|
1152
1318
|
}
|
package/src/git/context.ts
CHANGED
|
@@ -113,9 +113,18 @@ export interface GitServiceHooks {
|
|
|
113
113
|
};
|
|
114
114
|
/** Commit lifecycle hooks */
|
|
115
115
|
readonly commits?: {
|
|
116
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Called when a commit is signed successfully.
|
|
118
|
+
*
|
|
119
|
+
* Note: currently fired only from explicit-sign paths in the patch provider
|
|
120
|
+
* (where signing is requested via `-S` and confirmed up front). Operations
|
|
121
|
+
* that sign implicitly via `commit.gpgsign=true` (`commit`, `merge`, `pull`,
|
|
122
|
+
* `rebase`, `revert`, `cherryPick`) do not fire this hook because the
|
|
123
|
+
* library cannot cheaply confirm that signing actually occurred without an
|
|
124
|
+
* extra `git config`/`log --show-signature` call.
|
|
125
|
+
*/
|
|
117
126
|
onSigned?(format: SigningFormat, source?: unknown): void;
|
|
118
|
-
/** Called when commit signing fails */
|
|
127
|
+
/** Called when commit signing fails — fired from all signing-capable paths. */
|
|
119
128
|
onSigningFailed?(reason: SigningErrorReason, format: SigningFormat, source?: unknown): void;
|
|
120
129
|
};
|
|
121
130
|
/** Git operation hooks */
|
package/src/git/models/branch.ts
CHANGED
package/src/git/models/commit.ts
CHANGED
|
@@ -177,10 +177,7 @@ export class GitCommit implements GitRevisionReference {
|
|
|
177
177
|
|
|
178
178
|
const stashFiles = getSettledValue(stashFilesResult);
|
|
179
179
|
if (stashFiles?.length) {
|
|
180
|
-
commit.applyFileset({
|
|
181
|
-
files: stashFiles as readonly GitFileChange[],
|
|
182
|
-
filtered: commit.fileset?.filtered,
|
|
183
|
-
});
|
|
180
|
+
commit.applyFileset({ files: stashFiles, filtered: commit.fileset?.filtered });
|
|
184
181
|
}
|
|
185
182
|
enrichCommit(commit, { stashUntrackedFilesLoaded: true });
|
|
186
183
|
} else {
|
|
@@ -218,7 +215,6 @@ export class GitCommit implements GitRevisionReference {
|
|
|
218
215
|
readonly stashNumber: string | undefined;
|
|
219
216
|
readonly stashOnRef: string | undefined;
|
|
220
217
|
readonly tips: string[] | undefined;
|
|
221
|
-
readonly parentTimestamps?: GitStashParentInfo[] | undefined;
|
|
222
218
|
|
|
223
219
|
constructor(
|
|
224
220
|
public readonly repoPath: string,
|
|
@@ -234,13 +230,11 @@ export class GitCommit implements GitRevisionReference {
|
|
|
234
230
|
tips?: string[],
|
|
235
231
|
stashName?: string | undefined,
|
|
236
232
|
stashOnRef?: string | undefined,
|
|
237
|
-
parentTimestamps?: GitStashParentInfo[] | undefined,
|
|
238
233
|
shaLength: number = getAbbreviatedShaLength(),
|
|
239
234
|
) {
|
|
240
235
|
this.ref = sha;
|
|
241
236
|
this.shortSha = sha.substring(0, shaLength);
|
|
242
237
|
this.tips = tips;
|
|
243
|
-
this.parentTimestamps = parentTimestamps;
|
|
244
238
|
|
|
245
239
|
if (stashName) {
|
|
246
240
|
this.refType = 'stash';
|
|
@@ -457,7 +451,6 @@ export class GitCommit implements GitRevisionReference {
|
|
|
457
451
|
stats?: GitCommitStats | null;
|
|
458
452
|
stashUntrackedFilesLoaded?: boolean;
|
|
459
453
|
resolvedPreviousSha?: string;
|
|
460
|
-
parentTimestamps?: GitStashParentInfo[] | null;
|
|
461
454
|
}): T {
|
|
462
455
|
const commit = new GitCommit(
|
|
463
456
|
this.repoPath,
|
|
@@ -473,7 +466,6 @@ export class GitCommit implements GitRevisionReference {
|
|
|
473
466
|
this.tips,
|
|
474
467
|
this.stashName,
|
|
475
468
|
this.stashOnRef,
|
|
476
|
-
this.getChangedValue(changes.parentTimestamps, this.parentTimestamps),
|
|
477
469
|
this.shortSha.length,
|
|
478
470
|
);
|
|
479
471
|
commit._etagWorkingTree = this._etagWorkingTree;
|
|
@@ -522,7 +514,6 @@ export class GitCommit implements GitRevisionReference {
|
|
|
522
514
|
this.tips,
|
|
523
515
|
this.stashName,
|
|
524
516
|
this.stashOnRef,
|
|
525
|
-
this.parentTimestamps,
|
|
526
517
|
);
|
|
527
518
|
commit._etagWorkingTree = this._etagWorkingTree;
|
|
528
519
|
return commit as T;
|
|
@@ -672,17 +663,10 @@ export interface GitCommitStats<Files extends number | GitDiffFileStats = number
|
|
|
672
663
|
readonly deletions: number;
|
|
673
664
|
}
|
|
674
665
|
|
|
675
|
-
export interface GitStashParentInfo {
|
|
676
|
-
readonly sha: string;
|
|
677
|
-
readonly authorDate?: number;
|
|
678
|
-
readonly committerDate?: number;
|
|
679
|
-
}
|
|
680
|
-
|
|
681
666
|
export interface GitStashCommit extends GitCommit {
|
|
682
667
|
readonly refType: GitStashReference['refType'];
|
|
683
668
|
readonly stashName: string;
|
|
684
669
|
readonly stashNumber: string;
|
|
685
|
-
readonly parentTimestamps?: GitStashParentInfo[];
|
|
686
670
|
}
|
|
687
671
|
|
|
688
672
|
export type GitCommitWithFullDetails = GitCommit & { message: string; fileset: GitCommitFileset };
|
package/src/git/models/graph.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GitCommitReachability } from '../providers/commits.js';
|
|
1
2
|
import type { GitBranch } from './branch.js';
|
|
2
3
|
import type { GitStashCommit } from './commit.js';
|
|
3
4
|
import type { GitRemote } from './remote.js';
|
|
@@ -77,7 +78,7 @@ export interface GitGraphRow {
|
|
|
77
78
|
tags?: GitGraphRowTag[];
|
|
78
79
|
contexts?: GitGraphRowContexts;
|
|
79
80
|
stats?: GitGraphRowStats;
|
|
80
|
-
|
|
81
|
+
reachability?: GitCommitReachability;
|
|
81
82
|
isCurrentUser?: boolean;
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -97,8 +98,6 @@ export interface GitGraph {
|
|
|
97
98
|
|
|
98
99
|
/** SHAs reachable from HEAD (for enrichment: marking commits on the current branch) */
|
|
99
100
|
readonly reachableFromHEAD?: ReadonlySet<string>;
|
|
100
|
-
/** Map of SHA → set of branch names reachable from that SHA (for enrichment: branch context) */
|
|
101
|
-
readonly reachableFromBranches?: ReadonlyMap<string, ReadonlySet<string>>;
|
|
102
101
|
|
|
103
102
|
/** The rows for the set of commits requested */
|
|
104
103
|
readonly rows: GitGraphRow[];
|
|
@@ -179,6 +178,5 @@ export interface GraphContext {
|
|
|
179
178
|
readonly branchIdOfMainWorktree: string | undefined;
|
|
180
179
|
readonly stashes: ReadonlyMap<string, GitStashCommit> | undefined;
|
|
181
180
|
readonly reachableFromHEAD: ReadonlySet<string>;
|
|
182
|
-
readonly reachableFromBranches: ReadonlyMap<string, ReadonlySet<string>>;
|
|
183
181
|
readonly avatars: Map<string, string>;
|
|
184
182
|
}
|
|
@@ -48,7 +48,8 @@ export type RepositoryChange =
|
|
|
48
48
|
| 'remoteProviders'
|
|
49
49
|
| 'starred'
|
|
50
50
|
| 'opened'
|
|
51
|
-
| 'gkConfig'
|
|
51
|
+
| 'gkConfig'
|
|
52
|
+
| 'lastFetched';
|
|
52
53
|
|
|
53
54
|
export const repositoryChanges = exhaustiveArray<RepositoryChange>()([
|
|
54
55
|
'unknown',
|
|
@@ -71,6 +72,7 @@ export const repositoryChanges = exhaustiveArray<RepositoryChange>()([
|
|
|
71
72
|
'starred',
|
|
72
73
|
'opened',
|
|
73
74
|
'gkConfig',
|
|
75
|
+
'lastFetched',
|
|
74
76
|
]);
|
|
75
77
|
|
|
76
78
|
export interface RepositoryInit {
|
|
@@ -123,6 +125,7 @@ export class Repository {
|
|
|
123
125
|
protected readonly _watchService: RepositoryWatchService;
|
|
124
126
|
|
|
125
127
|
private _pendingWorkingTreeChange?: RepositoryWorkingTreeChangeEvent;
|
|
128
|
+
private _pendingWorkingTreeFlush = false;
|
|
126
129
|
private _repoChangeListener: UnifiedDisposable | undefined;
|
|
127
130
|
|
|
128
131
|
constructor(init: RepositoryInit) {
|
|
@@ -356,6 +359,9 @@ export class Repository {
|
|
|
356
359
|
/** Called when the watch service notifies of FETCH_HEAD changes. */
|
|
357
360
|
protected onFetchHeadChanged(): void {
|
|
358
361
|
this._lastFetched = undefined;
|
|
362
|
+
// Force-fire so the event arrives immediately (no debounce); downstream consumers must
|
|
363
|
+
// invalidate any cached fetch timestamp before reading a fresh value.
|
|
364
|
+
this.fireChange('lastFetched', true);
|
|
359
365
|
}
|
|
360
366
|
|
|
361
367
|
/** Called when .gitignore changes in the working tree. */
|
|
@@ -374,7 +380,15 @@ export class Repository {
|
|
|
374
380
|
this._onDidChange.fire(extEvent);
|
|
375
381
|
}
|
|
376
382
|
|
|
377
|
-
/**
|
|
383
|
+
/**
|
|
384
|
+
* Called by every {@link watchWorkingTree} subscription when its debounced batch arrives. Each
|
|
385
|
+
* call to {@link watchWorkingTree} adds a separate bridge listener on the underlying watch
|
|
386
|
+
* session, so a single fs change can invoke this method multiple times in the same microtask —
|
|
387
|
+
* once per active subscription. We accumulate paths into a single pending event and defer the
|
|
388
|
+
* actual fire to a microtask so back-to-back synchronous bridge calls collapse into ONE
|
|
389
|
+
* `_onDidChangeWorkingTree` emission. Without this coalescing, every WIP-dependent listener
|
|
390
|
+
* (graph, file history, compare branch, etc.) would fire N times for N active subscriptions.
|
|
391
|
+
*/
|
|
378
392
|
protected onWorkingTreeChanged(paths: ReadonlySet<string>): void {
|
|
379
393
|
this._updatedAt = Date.now();
|
|
380
394
|
|
|
@@ -384,10 +398,16 @@ export class Repository {
|
|
|
384
398
|
}
|
|
385
399
|
|
|
386
400
|
if (this._suspended) return;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
this.
|
|
390
|
-
|
|
401
|
+
if (this._pendingWorkingTreeFlush) return;
|
|
402
|
+
|
|
403
|
+
this._pendingWorkingTreeFlush = true;
|
|
404
|
+
queueMicrotask(() => {
|
|
405
|
+
this._pendingWorkingTreeFlush = false;
|
|
406
|
+
const e = this._pendingWorkingTreeChange;
|
|
407
|
+
if (e == null || this._suspended) return;
|
|
408
|
+
this._pendingWorkingTreeChange = undefined;
|
|
409
|
+
this._onDidChangeWorkingTree.fire(e);
|
|
410
|
+
});
|
|
391
411
|
}
|
|
392
412
|
|
|
393
413
|
@trace({ onlyExit: true })
|
|
@@ -135,10 +135,10 @@ export class GitWorktree {
|
|
|
135
135
|
: GitWorktree.formatDateFromNow(worktree);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
static async getStatus(worktree: GitWorktree): Promise<GitStatus | undefined> {
|
|
138
|
+
static async getStatus(worktree: GitWorktree, cancellation?: AbortSignal): Promise<GitStatus | undefined> {
|
|
139
139
|
if (worktree.type === 'bare') return undefined;
|
|
140
140
|
const repo = getRepositoryService(worktree.path);
|
|
141
|
-
return repo?.status.getStatus();
|
|
141
|
+
return repo?.status.getStatus(cancellation);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
static async hasWorkingChanges(
|
|
@@ -364,43 +364,6 @@ export function parseGitFileDiff(data: string, includeRawContent = false): Parse
|
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
export function parseGitDiffNameStatusFiles(data: string, repoPath: string): GitFile[] | undefined {
|
|
368
|
-
using sw = maybeStopWatch('Git.parseDiffNameStatusFiles', { log: { onlyExit: true, level: 'debug' } });
|
|
369
|
-
if (!data) {
|
|
370
|
-
sw?.stop({ suffix: ` no data` });
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const files: GitFile[] = [];
|
|
375
|
-
|
|
376
|
-
let status;
|
|
377
|
-
|
|
378
|
-
const fields = data.split('\0');
|
|
379
|
-
for (let i = 0; i < fields.length - 1; i++) {
|
|
380
|
-
status = fields[i][0];
|
|
381
|
-
if (status === '.') {
|
|
382
|
-
status = '?';
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
let originalPath;
|
|
386
|
-
// Renamed files are old followed by the new path
|
|
387
|
-
if (status === 'R' || status === 'C') {
|
|
388
|
-
if (i + 1 >= fields.length - 1) break;
|
|
389
|
-
|
|
390
|
-
originalPath = fields[++i];
|
|
391
|
-
}
|
|
392
|
-
if (i + 1 >= fields.length) break;
|
|
393
|
-
|
|
394
|
-
const path = fields[++i];
|
|
395
|
-
|
|
396
|
-
files.push({ status: status as GitFileStatus, path: path, originalPath: originalPath, repoPath: repoPath });
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
sw?.stop({ suffix: ` parsed ${files.length} files` });
|
|
400
|
-
|
|
401
|
-
return files;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
367
|
/**
|
|
405
368
|
* Parses the output of `git diff --numstat --summary -z`.
|
|
406
369
|
*
|
|
@@ -477,7 +440,7 @@ export function parseGitDiffNumStatFiles(data: string, repoPath: string): GitFil
|
|
|
477
440
|
repoPath: repoPath,
|
|
478
441
|
path: path,
|
|
479
442
|
originalPath: originalPath,
|
|
480
|
-
status:
|
|
443
|
+
status: originalPath ? 'R' : 'M',
|
|
481
444
|
stats: { additions: additions, deletions: deletions, changes: additions + deletions },
|
|
482
445
|
});
|
|
483
446
|
|
|
@@ -514,14 +477,14 @@ export function parseGitDiffNumStatFiles(data: string, repoPath: string): GitFil
|
|
|
514
477
|
if (createOrDelete != null) {
|
|
515
478
|
const file = files.get(normalizePath(createOrDeletePath));
|
|
516
479
|
if (file != null) {
|
|
517
|
-
file.status =
|
|
480
|
+
file.status = createOrDelete === 'create' ? 'A' : 'D';
|
|
518
481
|
}
|
|
519
482
|
} else if (renameOrCopy === 'copy') {
|
|
520
483
|
// Numstat defaulted to R; promote to C. Reconstruct the full new-side path by
|
|
521
484
|
// concatenating prefix + new-leaf + suffix, covering all compact and non-compact forms.
|
|
522
485
|
const file = files.get(normalizePath(renameRoot + renameNewLeaf + renameSuffix));
|
|
523
486
|
if (file != null) {
|
|
524
|
-
file.status = 'C'
|
|
487
|
+
file.status = 'C';
|
|
525
488
|
}
|
|
526
489
|
} else if (modeChangePath != null) {
|
|
527
490
|
// File-type boundary: 100xxx = regular file, 120000 = symlink, 160000 = gitlink.
|
|
@@ -529,7 +492,7 @@ export function parseGitDiffNumStatFiles(data: string, repoPath: string): GitFil
|
|
|
529
492
|
if (oldMode.substring(0, 2) !== newMode.substring(0, 2)) {
|
|
530
493
|
const file = files.get(normalizePath(modeChangePath));
|
|
531
494
|
if (file != null) {
|
|
532
|
-
file.status = 'T'
|
|
495
|
+
file.status = 'T';
|
|
533
496
|
}
|
|
534
497
|
}
|
|
535
498
|
}
|
|
@@ -564,7 +527,7 @@ export function parseGitApplyFiles(data: string, repoPath: string): GitFileChang
|
|
|
564
527
|
const [insertions, deletions, path] = line.split('\t');
|
|
565
528
|
files.set(
|
|
566
529
|
normalizePath(path),
|
|
567
|
-
new GitFileChange(repoPath, path, 'M'
|
|
530
|
+
new GitFileChange(repoPath, path, 'M', getUri(path), undefined, undefined, undefined, {
|
|
568
531
|
changes: 0,
|
|
569
532
|
additions: parseInt(insertions, 10),
|
|
570
533
|
deletions: parseInt(deletions, 10),
|
|
@@ -603,7 +566,7 @@ export function parseGitApplyFiles(data: string, repoPath: string): GitFileChang
|
|
|
603
566
|
new GitFileChange(
|
|
604
567
|
repoPath,
|
|
605
568
|
newPath,
|
|
606
|
-
|
|
569
|
+
renameOrCopy === 'copy' ? 'C' : 'R',
|
|
607
570
|
getUri(newPath),
|
|
608
571
|
originalPath,
|
|
609
572
|
getUri(originalPath),
|
|
@@ -618,7 +581,7 @@ export function parseGitApplyFiles(data: string, repoPath: string): GitFileChang
|
|
|
618
581
|
new GitFileChange(
|
|
619
582
|
repoPath,
|
|
620
583
|
file.path,
|
|
621
|
-
|
|
584
|
+
createOrDelete === 'create' ? 'A' : 'D',
|
|
622
585
|
getUri(file.path),
|
|
623
586
|
undefined,
|
|
624
587
|
undefined,
|