@gitkraken/core-gitlens 0.10.6 → 0.11.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 +33 -1
- package/dist/git/cache.d.ts +34 -2
- package/dist/git/cache.js +53 -7
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +1 -1
- package/dist/git/models/repository.d.ts +3 -2
- package/dist/git/models/repository.js +5 -4
- package/dist/git/models/repository.js.map +1 -1
- package/dist/git/providers/branches.d.ts +22 -0
- package/dist/git/providers/config.d.ts +3 -1
- package/dist/git/providers/diff.d.ts +1 -0
- package/dist/git/providers/provider.d.ts +13 -1
- package/dist/git/providers/staging.d.ts +1 -1
- package/dist/git/service.d.ts +17 -1
- package/dist/git/service.js +59 -8
- package/dist/git/service.js.map +1 -1
- package/dist/git/watching/changeEvent.d.ts +48 -5
- package/dist/git/watching/changeEvent.js +82 -7
- package/dist/git/watching/changeEvent.js.map +1 -1
- package/dist/git/watching/classifyChange.d.ts +13 -2
- package/dist/git/watching/classifyChange.js +40 -5
- package/dist/git/watching/classifyChange.js.map +1 -1
- package/dist/git/watching/gitIgnoreFilter.d.ts +57 -10
- package/dist/git/watching/gitIgnoreFilter.js +186 -29
- package/dist/git/watching/gitIgnoreFilter.js.map +1 -1
- package/dist/git/watching/initWatcher.d.ts +5 -1
- package/dist/git/watching/initWatcher.js +1 -1
- package/dist/git/watching/initWatcher.js.map +1 -1
- package/dist/git/watching/provider.d.ts +33 -8
- package/dist/git/watching/watchGroup.d.ts +13 -2
- package/dist/git/watching/watchGroup.js +60 -14
- package/dist/git/watching/watchGroup.js.map +1 -1
- package/dist/git/watching/watchService.d.ts +42 -1
- package/dist/git/watching/watchService.js +172 -20
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git/watching/watchSession.d.ts +50 -17
- package/dist/git/watching/watchSession.js +274 -83
- package/dist/git/watching/watchSession.js.map +1 -1
- package/dist/git/watching/watcherPatterns.d.ts +13 -2
- package/dist/git/watching/watcherPatterns.js +22 -2
- package/dist/git/watching/watcherPatterns.js.map +1 -1
- package/dist/git/watching/worktreeSummary.d.ts +121 -0
- package/dist/git/watching/worktreeSummary.js +427 -0
- package/dist/git/watching/worktreeSummary.js.map +1 -0
- package/dist/git-cli/cliGitProvider.d.ts +6 -1
- package/dist/git-cli/cliGitProvider.js +87 -2
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.js +1 -1
- package/dist/git-cli/providers/blame.js +1 -1
- package/dist/git-cli/providers/branches.d.ts +32 -1
- package/dist/git-cli/providers/branches.js +195 -0
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.js +1 -1
- package/dist/git-cli/providers/config.d.ts +3 -0
- package/dist/git-cli/providers/config.js +14 -8
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/contributors.js +1 -1
- package/dist/git-cli/providers/diff.d.ts +3 -0
- package/dist/git-cli/providers/diff.js +3 -2
- package/dist/git-cli/providers/diff.js.map +1 -1
- package/dist/git-cli/providers/graph.js +1 -1
- package/dist/git-cli/providers/maintenance.js +1 -1
- package/dist/git-cli/providers/pausedOperations.js +2 -2
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.js +1 -1
- package/dist/git-cli/providers/staging.js +2 -2
- package/dist/git-cli/providers/status.js +1 -1
- package/dist/git-cli/service.js +1 -0
- package/dist/git-cli/service.js.map +1 -1
- package/dist/ipc/discovery.js +1 -1
- package/dist/ipc/ipcServer.js +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
- package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
- package/dist/plus/agents/providers/gkAgentProvider.js +2 -2
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
- package/dist/plus/git-github/api/github.d.ts +1 -1
- package/dist/plus/git-github/api/github.js +2 -1
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/providers/github/blame.js +1 -1
- package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js +1 -1
- package/dist/plus/integrations/context.d.ts +1 -1
- package/dist/plus/integrations/integrationService.js +1 -1
- package/dist/plus/integrations/models/integration.d.ts +1 -1
- package/dist/plus/integrations/models/integration.js +2 -2
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +2 -0
- package/dist/plus/integrations/providers/jira.js +5 -0
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +7 -0
- package/dist/plus/integrations/providers/linear.js +19 -0
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/trello.d.ts +8 -0
- package/dist/plus/integrations/providers/trello.js +22 -0
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/reads/currentAccount.d.ts +1 -1
- package/dist/plus/integrations/reads/currentAccount.js +1 -1
- package/dist/plus/integrations/reads/currentAccount.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +1 -0
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/utils/env/node/exec.js +2 -2
- package/dist/utils/event.d.ts +1 -1
- package/docs/integrations.md +6 -6
- package/docs/kepler-read-api-parity.md +2 -2
- package/package.json +1 -1
|
@@ -1,24 +1,72 @@
|
|
|
1
1
|
import { filter, some } from "../../utils/iterable.js";
|
|
2
2
|
//#region ../git/src/watching/changeEvent.ts
|
|
3
|
+
function isRefChangeKind(change) {
|
|
4
|
+
return change === "heads" || change === "remotes" || change === "tags" || change === "stash";
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The kind of ref a full ref name (or ref directory) belongs to. A pseudo-ref (no `refs/` prefix, e.g. `HEAD`,
|
|
8
|
+
* `ORIG_HEAD`) counts as `heads`; a ref outside the watched namespaces (e.g. `refs/notes/x`) has no kind.
|
|
9
|
+
*/
|
|
10
|
+
function getRefChangeKind(ref) {
|
|
11
|
+
if (!ref.startsWith("refs/")) return "heads";
|
|
12
|
+
if (ref.startsWith("refs/heads/")) return "heads";
|
|
13
|
+
if (ref.startsWith("refs/remotes/")) return "remotes";
|
|
14
|
+
if (ref.startsWith("refs/tags/")) return "tags";
|
|
15
|
+
if (ref === "refs/stash") return "stash";
|
|
16
|
+
}
|
|
3
17
|
/**
|
|
4
18
|
* An event describing changes to a repository, produced by the watching pipeline.
|
|
5
19
|
*
|
|
6
20
|
* Changes are coalesced within a debounce window — a single event may represent
|
|
7
|
-
* multiple filesystem changes. Use {@link changed} to test for specific change types
|
|
21
|
+
* multiple filesystem changes. Use {@link changed} to test for specific change types,
|
|
22
|
+
* and {@link mayHaveChangedRef} to test whether a specific ref may have moved.
|
|
8
23
|
*/
|
|
9
24
|
var WatcherRepoChangeEvent = class WatcherRepoChangeEvent {
|
|
10
25
|
repoPath;
|
|
11
26
|
_changes;
|
|
12
|
-
|
|
27
|
+
_refs;
|
|
28
|
+
_unnamedRefKinds;
|
|
29
|
+
constructor(repoPath, changes, refs) {
|
|
13
30
|
this.repoPath = repoPath;
|
|
14
31
|
this._changes = new Set(changes);
|
|
32
|
+
if (refs == null) {
|
|
33
|
+
this._refs = /* @__PURE__ */ new Set();
|
|
34
|
+
this._unnamedRefKinds = new Set(filter(changes, isRefChangeKind));
|
|
35
|
+
} else {
|
|
36
|
+
this._refs = new Set(refs.names);
|
|
37
|
+
this._unnamedRefKinds = new Set(refs.unnamed);
|
|
38
|
+
}
|
|
15
39
|
}
|
|
16
40
|
get changes() {
|
|
17
41
|
return this._changes;
|
|
18
42
|
}
|
|
43
|
+
/** Full ref names (or ref directories, or pseudo-refs) known to have changed. See {@link WatcherRefChanges.names}. */
|
|
44
|
+
get refs() {
|
|
45
|
+
return this._refs;
|
|
46
|
+
}
|
|
47
|
+
/** Ref kinds that changed without a name — any ref of these kinds may have moved */
|
|
48
|
+
get unnamedRefKinds() {
|
|
49
|
+
return this._unnamedRefKinds;
|
|
50
|
+
}
|
|
19
51
|
toString(changesOnly = false) {
|
|
20
52
|
const changeList = [...this._changes].join(", ");
|
|
21
|
-
|
|
53
|
+
const refCount = this._refs.size;
|
|
54
|
+
if (changesOnly) return refCount ? `changes=${changeList}, refs=${refCount}` : `changes=${changeList}`;
|
|
55
|
+
return refCount ? `{ repoPath: ${this.repoPath}, changes: ${changeList}, refs: ${refCount} }` : `{ repoPath: ${this.repoPath}, changes: ${changeList} }`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Test whether the given ref may have moved in this event.
|
|
59
|
+
*
|
|
60
|
+
* @param ref - A full ref name (`refs/heads/main`) or a pseudo-ref (`HEAD`).
|
|
61
|
+
* @returns `false` when the ref's kind didn't change (or the ref is outside the watched kinds); `true` when its kind
|
|
62
|
+
* changed without a name, or when the ref itself or a ref directory above it changed. `HEAD` is usually a symref
|
|
63
|
+
* to the checked-out branch, so it may have moved whenever any `heads` ref did.
|
|
64
|
+
*/
|
|
65
|
+
mayHaveChangedRef(ref) {
|
|
66
|
+
const kind = getRefChangeKind(ref);
|
|
67
|
+
if (kind == null || !this._changes.has(kind)) return false;
|
|
68
|
+
if (this._unnamedRefKinds.has(kind) || ref === "HEAD") return true;
|
|
69
|
+
return findCoveringRefName(this._refs, ref) != null;
|
|
22
70
|
}
|
|
23
71
|
/**
|
|
24
72
|
* Test whether any of the specified change types are present in the event.
|
|
@@ -51,12 +99,39 @@ var WatcherRepoChangeEvent = class WatcherRepoChangeEvent {
|
|
|
51
99
|
}
|
|
52
100
|
return [...filter(changes, (c) => affected.includes(c))].length === changes.size;
|
|
53
101
|
}
|
|
54
|
-
/**
|
|
55
|
-
with
|
|
56
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Coalesce: return a new event with all changes and refs from both this and the given set. When `refs` is omitted,
|
|
104
|
+
* every ref kind in `changes` counts as unnamed.
|
|
105
|
+
*/
|
|
106
|
+
with(changes, refs) {
|
|
107
|
+
const names = [...this._refs];
|
|
108
|
+
const unnamed = [...this._unnamedRefKinds];
|
|
109
|
+
if (refs == null) unnamed.push(...filter(changes, isRefChangeKind));
|
|
110
|
+
else {
|
|
111
|
+
if (refs.names != null) names.push(...refs.names);
|
|
112
|
+
if (refs.unnamed != null) unnamed.push(...refs.unnamed);
|
|
113
|
+
}
|
|
114
|
+
return new WatcherRepoChangeEvent(this.repoPath, [...this._changes, ...changes], {
|
|
115
|
+
names,
|
|
116
|
+
unnamed
|
|
117
|
+
});
|
|
57
118
|
}
|
|
58
119
|
};
|
|
120
|
+
/**
|
|
121
|
+
* Returns the name in `names` that covers `ref` — `ref` itself, or a ref directory above it (compared on `/`
|
|
122
|
+
* boundaries, so `refs/heads/fe` doesn't cover `refs/heads/feature`) — or `undefined` if none does.
|
|
123
|
+
*/
|
|
124
|
+
function findCoveringRefName(names, ref) {
|
|
125
|
+
if (names.size === 0) return void 0;
|
|
126
|
+
if (names.has(ref)) return ref;
|
|
127
|
+
let index = ref.lastIndexOf("/");
|
|
128
|
+
while (index > 0) {
|
|
129
|
+
const dir = ref.substring(0, index);
|
|
130
|
+
if (names.has(dir)) return dir;
|
|
131
|
+
index = ref.lastIndexOf("/", index - 1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
59
134
|
//#endregion
|
|
60
|
-
export { WatcherRepoChangeEvent };
|
|
135
|
+
export { WatcherRepoChangeEvent, findCoveringRefName, getRefChangeKind, isRefChangeKind };
|
|
61
136
|
|
|
62
137
|
//# sourceMappingURL=changeEvent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changeEvent.js","names":[],"sources":["../../../../git/src/watching/changeEvent.ts"],"sourcesContent":["import { filter, some } from '@gitlens/utils/iterable.js';\nimport type { RepositoryChange } from '../models/repository.js';\n\n/**\n * An event describing changes to a repository, produced by the watching pipeline.\n *\n * Changes are coalesced within a debounce window — a single event may represent\n * multiple filesystem changes. Use {@link changed} to test for specific change types.\n */\nexport class WatcherRepoChangeEvent {\n\tprotected readonly _changes: Set<RepositoryChange>;\n\n\tconstructor(\n\t\t/** The repository path this event is for */\n\t\tpublic readonly repoPath: string,\n\t\tchanges: RepositoryChange[],\n\t) {\n\t\tthis._changes = new Set(changes);\n\t}\n\n\tget changes(): ReadonlySet<RepositoryChange> {\n\t\treturn this._changes;\n\t}\n\n\ttoString(changesOnly: boolean = false): string {\n\t\tconst changeList = [...this._changes].join(', ');\n\t\treturn changesOnly ? `changes=${changeList}` : `{ repoPath: ${this.repoPath}, changes: ${changeList} }`;\n\t}\n\n\t/**\n\t * Test whether any of the specified change types are present in the event.\n\t *\n\t * @param affected - Change types to test for.\n\t * @returns `true` if any of the specified changes are present.\n\t */\n\tchanged(...affected: RepositoryChange[]): boolean {\n\t\treturn some(this._changes, c => affected.includes(c));\n\t}\n\n\t/**\n\t * Test whether the event contains ONLY the specified change types.\n\t *\n\t * `pausedOp` is treated as a union of `cherryPick`, `merge`, `rebase`,\n\t * and `revert` for convenience.\n\t *\n\t * @param affected - Change types to test for.\n\t * @returns `true` if the event contains only the specified changes.\n\t */\n\tchangedExclusive(...affected: RepositoryChange[]): boolean {\n\t\tlet changes = this._changes;\n\n\t\t// When checking for specific paused operation types, also accept the union type\n\t\tif (\n\t\t\taffected.includes('cherryPick') ||\n\t\t\taffected.includes('merge') ||\n\t\t\taffected.includes('rebase') ||\n\t\t\taffected.includes('revert')\n\t\t) {\n\t\t\tif (!affected.includes('pausedOp')) {\n\t\t\t\taffected = [...affected, 'pausedOp'];\n\t\t\t}\n\t\t} else if (affected.includes('pausedOp')) {\n\t\t\t// When checking for the union type exclusively, ignore specific subtypes\n\t\t\tchanges = new Set(changes);\n\t\t\tchanges.delete('cherryPick');\n\t\t\tchanges.delete('merge');\n\t\t\tchanges.delete('rebase');\n\t\t\tchanges.delete('revert');\n\t\t}\n\n\t\tconst intersection = [...filter(changes, c => affected.includes(c))];\n\t\treturn intersection.length === changes.size;\n\t}\n\n\t/** Coalesce: return a new event with all changes from both this and the given set */\n\twith(changes: RepositoryChange[]): WatcherRepoChangeEvent {\n\t\treturn new WatcherRepoChangeEvent(this.repoPath, [...this._changes, ...changes]);\n\t}\n}\n\n/**\n * An event describing working tree file changes, produced by the working tree pipeline.\n *\n * Paths have already been filtered through the gitignore filter and noise filter.\n */\nexport interface WorkingTreeChangeEvent {\n\treadonly repoPath: string;\n\t/** Absolute paths of changed files (post-gitignore filtering). Partial when {@link incomplete}. */\n\treadonly paths: ReadonlySet<string>;\n\t/**\n\t * `true` when more paths changed than the accumulator retains, so {@link paths} is a partial set and a\n\t * miss does NOT mean the file is unchanged. Consumers testing membership must treat this as a match.\n\t */\n\treadonly incomplete: boolean;\n}\n"],"mappings":";;;;;;;;AASA,IAAa,yBAAb,MAAa,uBAAuB;CAKlB;CAJjB;CAEA,YAEC,UACA,SACC;EAFe,KAAA,WAAA;EAGhB,KAAK,WAAW,IAAI,IAAI,OAAO;CAChC;CAEA,IAAI,UAAyC;EAC5C,OAAO,KAAK;CACb;CAEA,SAAS,cAAuB,OAAe;EAC9C,MAAM,aAAa,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,KAAK,IAAI;EAC/C,OAAO,cAAc,WAAW,eAAe,eAAe,KAAK,SAAS,aAAa,WAAW;CACrG;;;;;;;CAQA,QAAQ,GAAG,UAAuC;EACjD,OAAO,KAAK,KAAK,WAAU,MAAK,SAAS,SAAS,CAAC,CAAC;CACrD;;;;;;;;;;CAWA,iBAAiB,GAAG,UAAuC;EAC1D,IAAI,UAAU,KAAK;EAGnB,IACC,SAAS,SAAS,YAAY,KAC9B,SAAS,SAAS,OAAO,KACzB,SAAS,SAAS,QAAQ,KAC1B,SAAS,SAAS,QAAQ,GAEtB;OAAA,CAAC,SAAS,SAAS,UAAU,GAChC,WAAW,CAAC,GAAG,UAAU,UAAU;EAAA,OAE9B,IAAI,SAAS,SAAS,UAAU,GAAG;GAEzC,UAAU,IAAI,IAAI,OAAO;GACzB,QAAQ,OAAO,YAAY;GAC3B,QAAQ,OAAO,OAAO;GACtB,QAAQ,OAAO,QAAQ;GACvB,QAAQ,OAAO,QAAQ;EACxB;EAGA,OAAO,CADe,GAAG,OAAO,UAAS,MAAK,SAAS,SAAS,CAAC,CAAC,CAChD,CAAC,CAAC,WAAW,QAAQ;CACxC;;CAGA,KAAK,SAAqD;EACzD,OAAO,IAAI,uBAAuB,KAAK,UAAU,CAAC,GAAG,KAAK,UAAU,GAAG,OAAO,CAAC;CAChF;AACD"}
|
|
1
|
+
{"version":3,"file":"changeEvent.js","names":[],"sources":["../../../../git/src/watching/changeEvent.ts"],"sourcesContent":["import { filter, some } from '@gitlens/utils/iterable.js';\nimport type { RepositoryChange } from '../models/repository.js';\n\n/** The {@link RepositoryChange} kinds that describe ref movement, which an event can attribute to named refs */\nexport type RefChangeKind = 'heads' | 'remotes' | 'tags' | 'stash';\n\nexport interface WatcherRefChanges {\n\t/** Full ref names whose files changed (`refs/heads/main`), plus per-worktree pseudo-refs (`HEAD`, `ORIG_HEAD`). A name may be a ref directory and then covers every ref beneath it. */\n\treadonly names?: Iterable<string>;\n\t/** Ref kinds that changed without a name (packed-refs rewrite, config, shallow/replace, an injected change): any ref of that kind may have moved. */\n\treadonly unnamed?: Iterable<RefChangeKind>;\n}\n\nexport function isRefChangeKind(change: RepositoryChange): change is RefChangeKind {\n\treturn change === 'heads' || change === 'remotes' || change === 'tags' || change === 'stash';\n}\n\n/**\n * The kind of ref a full ref name (or ref directory) belongs to. A pseudo-ref (no `refs/` prefix, e.g. `HEAD`,\n * `ORIG_HEAD`) counts as `heads`; a ref outside the watched namespaces (e.g. `refs/notes/x`) has no kind.\n */\nexport function getRefChangeKind(ref: string): RefChangeKind | undefined {\n\tif (!ref.startsWith('refs/')) return 'heads';\n\tif (ref.startsWith('refs/heads/')) return 'heads';\n\tif (ref.startsWith('refs/remotes/')) return 'remotes';\n\tif (ref.startsWith('refs/tags/')) return 'tags';\n\tif (ref === 'refs/stash') return 'stash';\n\n\treturn undefined;\n}\n\n/**\n * An event describing changes to a repository, produced by the watching pipeline.\n *\n * Changes are coalesced within a debounce window — a single event may represent\n * multiple filesystem changes. Use {@link changed} to test for specific change types,\n * and {@link mayHaveChangedRef} to test whether a specific ref may have moved.\n */\nexport class WatcherRepoChangeEvent {\n\tprotected readonly _changes: Set<RepositoryChange>;\n\tprivate readonly _refs: Set<string>;\n\tprivate readonly _unnamedRefKinds: Set<RefChangeKind>;\n\n\tconstructor(\n\t\t/** The repository path this event is for */\n\t\tpublic readonly repoPath: string,\n\t\tchanges: RepositoryChange[],\n\t\t/** Which refs changed; when omitted, every ref kind in `changes` is unnamed (any ref of that kind may have moved) */\n\t\trefs?: WatcherRefChanges,\n\t) {\n\t\tthis._changes = new Set(changes);\n\t\tif (refs == null) {\n\t\t\tthis._refs = new Set();\n\t\t\tthis._unnamedRefKinds = new Set(filter(changes, isRefChangeKind));\n\t\t} else {\n\t\t\tthis._refs = new Set(refs.names);\n\t\t\tthis._unnamedRefKinds = new Set(refs.unnamed);\n\t\t}\n\t}\n\n\tget changes(): ReadonlySet<RepositoryChange> {\n\t\treturn this._changes;\n\t}\n\n\t/** Full ref names (or ref directories, or pseudo-refs) known to have changed. See {@link WatcherRefChanges.names}. */\n\tget refs(): ReadonlySet<string> {\n\t\treturn this._refs;\n\t}\n\n\t/** Ref kinds that changed without a name — any ref of these kinds may have moved */\n\tget unnamedRefKinds(): ReadonlySet<RefChangeKind> {\n\t\treturn this._unnamedRefKinds;\n\t}\n\n\ttoString(changesOnly: boolean = false): string {\n\t\tconst changeList = [...this._changes].join(', ');\n\t\tconst refCount = this._refs.size;\n\t\tif (changesOnly) return refCount ? `changes=${changeList}, refs=${refCount}` : `changes=${changeList}`;\n\n\t\treturn refCount\n\t\t\t? `{ repoPath: ${this.repoPath}, changes: ${changeList}, refs: ${refCount} }`\n\t\t\t: `{ repoPath: ${this.repoPath}, changes: ${changeList} }`;\n\t}\n\n\t/**\n\t * Test whether the given ref may have moved in this event.\n\t *\n\t * @param ref - A full ref name (`refs/heads/main`) or a pseudo-ref (`HEAD`).\n\t * @returns `false` when the ref's kind didn't change (or the ref is outside the watched kinds); `true` when its kind\n\t * changed without a name, or when the ref itself or a ref directory above it changed. `HEAD` is usually a symref\n\t * to the checked-out branch, so it may have moved whenever any `heads` ref did.\n\t */\n\tmayHaveChangedRef(ref: string): boolean {\n\t\tconst kind = getRefChangeKind(ref);\n\t\tif (kind == null || !this._changes.has(kind)) return false;\n\t\tif (this._unnamedRefKinds.has(kind) || ref === 'HEAD') return true;\n\n\t\treturn findCoveringRefName(this._refs, ref) != null;\n\t}\n\n\t/**\n\t * Test whether any of the specified change types are present in the event.\n\t *\n\t * @param affected - Change types to test for.\n\t * @returns `true` if any of the specified changes are present.\n\t */\n\tchanged(...affected: RepositoryChange[]): boolean {\n\t\treturn some(this._changes, c => affected.includes(c));\n\t}\n\n\t/**\n\t * Test whether the event contains ONLY the specified change types.\n\t *\n\t * `pausedOp` is treated as a union of `cherryPick`, `merge`, `rebase`,\n\t * and `revert` for convenience.\n\t *\n\t * @param affected - Change types to test for.\n\t * @returns `true` if the event contains only the specified changes.\n\t */\n\tchangedExclusive(...affected: RepositoryChange[]): boolean {\n\t\tlet changes = this._changes;\n\n\t\t// When checking for specific paused operation types, also accept the union type\n\t\tif (\n\t\t\taffected.includes('cherryPick') ||\n\t\t\taffected.includes('merge') ||\n\t\t\taffected.includes('rebase') ||\n\t\t\taffected.includes('revert')\n\t\t) {\n\t\t\tif (!affected.includes('pausedOp')) {\n\t\t\t\taffected = [...affected, 'pausedOp'];\n\t\t\t}\n\t\t} else if (affected.includes('pausedOp')) {\n\t\t\t// When checking for the union type exclusively, ignore specific subtypes\n\t\t\tchanges = new Set(changes);\n\t\t\tchanges.delete('cherryPick');\n\t\t\tchanges.delete('merge');\n\t\t\tchanges.delete('rebase');\n\t\t\tchanges.delete('revert');\n\t\t}\n\n\t\tconst intersection = [...filter(changes, c => affected.includes(c))];\n\t\treturn intersection.length === changes.size;\n\t}\n\n\t/**\n\t * Coalesce: return a new event with all changes and refs from both this and the given set. When `refs` is omitted,\n\t * every ref kind in `changes` counts as unnamed.\n\t */\n\twith(changes: RepositoryChange[], refs?: WatcherRefChanges): WatcherRepoChangeEvent {\n\t\tconst names = [...this._refs];\n\t\tconst unnamed = [...this._unnamedRefKinds];\n\t\tif (refs == null) {\n\t\t\tunnamed.push(...filter(changes, isRefChangeKind));\n\t\t} else {\n\t\t\tif (refs.names != null) {\n\t\t\t\tnames.push(...refs.names);\n\t\t\t}\n\t\t\tif (refs.unnamed != null) {\n\t\t\t\tunnamed.push(...refs.unnamed);\n\t\t\t}\n\t\t}\n\n\t\treturn new WatcherRepoChangeEvent(this.repoPath, [...this._changes, ...changes], {\n\t\t\tnames: names,\n\t\t\tunnamed: unnamed,\n\t\t});\n\t}\n}\n\n/**\n * Returns the name in `names` that covers `ref` — `ref` itself, or a ref directory above it (compared on `/`\n * boundaries, so `refs/heads/fe` doesn't cover `refs/heads/feature`) — or `undefined` if none does.\n */\nexport function findCoveringRefName(names: ReadonlySet<string>, ref: string): string | undefined {\n\tif (names.size === 0) return undefined;\n\tif (names.has(ref)) return ref;\n\n\tlet index = ref.lastIndexOf('/');\n\twhile (index > 0) {\n\t\tconst dir = ref.substring(0, index);\n\t\tif (names.has(dir)) return dir;\n\n\t\tindex = ref.lastIndexOf('/', index - 1);\n\t}\n\treturn undefined;\n}\n\n/**\n * An event describing working tree file changes, produced by the working tree pipeline.\n *\n * Paths have already been filtered through the gitignore filter and noise filter.\n */\nexport interface WorkingTreeChangeEvent {\n\treadonly repoPath: string;\n\t/**\n\t * Absolute paths of changed files or directories (post-gitignore filtering). A directory stands for everything\n\t * beneath it. Partial when {@link incomplete}.\n\t */\n\treadonly paths: ReadonlySet<string>;\n\t/**\n\t * `true` when more paths changed than the accumulator retains, so {@link paths} is a partial set and a\n\t * miss does NOT mean the file is unchanged. Consumers testing membership must treat this as a match.\n\t */\n\treadonly incomplete: boolean;\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { RepositoryChange } from "../models/repository.js";
|
|
2
2
|
//#region ../git/src/watching/classifyChange.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Everything a `.git` watcher can report. Used when events were lost (`overflow`), so every cache type those
|
|
5
|
+
* kinds clear is refreshed. Deliberately not `'unknown'`: `Cache.onRepositoryChanged` treats that as a close and
|
|
6
|
+
* unregisters the path, after which shared evictions stop reaching it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const allWatchedRepositoryChanges: readonly RepositoryChange[];
|
|
3
9
|
/**
|
|
4
10
|
* Maps a path relative to a `.git` directory to the corresponding
|
|
5
11
|
* {@link RepositoryChange} types. This is pure Git knowledge — the
|
|
6
12
|
* regex and switch table encode which files in `.git/` correspond
|
|
7
13
|
* to which logical repository changes.
|
|
8
14
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
15
|
+
* `worktrees` means the worktree list, or what `git worktree list` reports per worktree, changed:
|
|
16
|
+
* `worktrees`, `worktrees/<n>` (add/remove/prune) and `worktrees/<n>/{HEAD,locked,gitdir}`. Any other
|
|
17
|
+
* path under `worktrees/<n>/` (index, `*_HEAD`, `MERGE_*`, rebase state, logs, …) is that worktree's
|
|
18
|
+
* own state, which its own gitdir watcher classifies, so it yields `undefined` here.
|
|
19
|
+
*
|
|
20
|
+
* @param relativePath - Path relative to the common `.git` directory or a worktree's gitdir
|
|
21
|
+
* (e.g., `refs/heads/main`, `HEAD`, `config`, `worktrees/foo/HEAD`)
|
|
11
22
|
* @returns An array of change types, or `undefined` if the path
|
|
12
23
|
* is noise or unrecognized. `undefined` for `FETCH_HEAD` which
|
|
13
24
|
* is intentionally not mapped to a change type (the extension
|
|
@@ -1,13 +1,40 @@
|
|
|
1
1
|
//#region ../git/src/watching/classifyChange.ts
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Everything a `.git` watcher can report. Used when events were lost (`overflow`), so every cache type those
|
|
4
|
+
* kinds clear is refreshed. Deliberately not `'unknown'`: `Cache.onRepositoryChanged` treats that as a close and
|
|
5
|
+
* unregisters the path, after which shared evictions stop reaching it.
|
|
6
|
+
*/
|
|
7
|
+
const allWatchedRepositoryChanges = [
|
|
8
|
+
"index",
|
|
9
|
+
"head",
|
|
10
|
+
"heads",
|
|
11
|
+
"tags",
|
|
12
|
+
"stash",
|
|
13
|
+
"remotes",
|
|
14
|
+
"worktrees",
|
|
15
|
+
"config",
|
|
16
|
+
"cherryPick",
|
|
17
|
+
"merge",
|
|
18
|
+
"rebase",
|
|
19
|
+
"revert",
|
|
20
|
+
"pausedOp",
|
|
21
|
+
"ignores",
|
|
22
|
+
"gkConfig"
|
|
23
|
+
];
|
|
24
|
+
const classifyRegex = /(index|HEAD|FETCH_HEAD|ORIG_HEAD|CHERRY_PICK_HEAD|MERGE_HEAD|REBASE_HEAD|rebase-merge|rebase-apply|sequencer|REVERT_HEAD|config|gk\/config|info\/exclude|refs\/(?:heads|remotes|stash|tags|replace)|packed-refs|shallow)/;
|
|
3
25
|
/**
|
|
4
26
|
* Maps a path relative to a `.git` directory to the corresponding
|
|
5
27
|
* {@link RepositoryChange} types. This is pure Git knowledge — the
|
|
6
28
|
* regex and switch table encode which files in `.git/` correspond
|
|
7
29
|
* to which logical repository changes.
|
|
8
30
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
31
|
+
* `worktrees` means the worktree list, or what `git worktree list` reports per worktree, changed:
|
|
32
|
+
* `worktrees`, `worktrees/<n>` (add/remove/prune) and `worktrees/<n>/{HEAD,locked,gitdir}`. Any other
|
|
33
|
+
* path under `worktrees/<n>/` (index, `*_HEAD`, `MERGE_*`, rebase state, logs, …) is that worktree's
|
|
34
|
+
* own state, which its own gitdir watcher classifies, so it yields `undefined` here.
|
|
35
|
+
*
|
|
36
|
+
* @param relativePath - Path relative to the common `.git` directory or a worktree's gitdir
|
|
37
|
+
* (e.g., `refs/heads/main`, `HEAD`, `config`, `worktrees/foo/HEAD`)
|
|
11
38
|
* @returns An array of change types, or `undefined` if the path
|
|
12
39
|
* is noise or unrecognized. `undefined` for `FETCH_HEAD` which
|
|
13
40
|
* is intentionally not mapped to a change type (the extension
|
|
@@ -15,6 +42,15 @@ const classifyRegex = /(worktrees|index|HEAD|FETCH_HEAD|ORIG_HEAD|CHERRY_PICK_HE
|
|
|
15
42
|
*/
|
|
16
43
|
function classifyGitDirChange(relativePath) {
|
|
17
44
|
if (relativePath.endsWith("/git-rebase-todo") || relativePath.endsWith("/git-rebase-todo.backup")) return;
|
|
45
|
+
if (relativePath.startsWith("worktrees")) {
|
|
46
|
+
if (relativePath.length === 9) return ["worktrees"];
|
|
47
|
+
if (relativePath.charCodeAt(9) === 47) {
|
|
48
|
+
const idEnd = relativePath.indexOf("/", 10);
|
|
49
|
+
if (idEnd === -1) return relativePath.length > 10 ? ["worktrees"] : void 0;
|
|
50
|
+
const file = relativePath.substring(idEnd + 1);
|
|
51
|
+
return file === "HEAD" || file === "locked" || file === "gitdir" ? ["worktrees"] : void 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
18
54
|
const match = classifyRegex.exec(relativePath);
|
|
19
55
|
if (match == null) return void 0;
|
|
20
56
|
switch (match[1]) {
|
|
@@ -43,11 +79,10 @@ function classifyGitDirChange(relativePath) {
|
|
|
43
79
|
"remotes",
|
|
44
80
|
"tags"
|
|
45
81
|
];
|
|
46
|
-
case "worktrees": return ["worktrees"];
|
|
47
82
|
default: return;
|
|
48
83
|
}
|
|
49
84
|
}
|
|
50
85
|
//#endregion
|
|
51
|
-
export { classifyGitDirChange };
|
|
86
|
+
export { allWatchedRepositoryChanges, classifyGitDirChange };
|
|
52
87
|
|
|
53
88
|
//# sourceMappingURL=classifyChange.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifyChange.js","names":[],"sources":["../../../../git/src/watching/classifyChange.ts"],"sourcesContent":["import type { RepositoryChange } from '../models/repository.js';\n\nconst classifyRegex =\n\t/(
|
|
1
|
+
{"version":3,"file":"classifyChange.js","names":[],"sources":["../../../../git/src/watching/classifyChange.ts"],"sourcesContent":["import type { RepositoryChange } from '../models/repository.js';\n\n/**\n * Everything a `.git` watcher can report. Used when events were lost (`overflow`), so every cache type those\n * kinds clear is refreshed. Deliberately not `'unknown'`: `Cache.onRepositoryChanged` treats that as a close and\n * unregisters the path, after which shared evictions stop reaching it.\n */\nexport const allWatchedRepositoryChanges: readonly RepositoryChange[] = [\n\t'index',\n\t'head',\n\t'heads',\n\t'tags',\n\t'stash',\n\t'remotes',\n\t'worktrees',\n\t'config',\n\t'cherryPick',\n\t'merge',\n\t'rebase',\n\t'revert',\n\t'pausedOp',\n\t'ignores',\n\t'gkConfig',\n];\n\nconst classifyRegex =\n\t/(index|HEAD|FETCH_HEAD|ORIG_HEAD|CHERRY_PICK_HEAD|MERGE_HEAD|REBASE_HEAD|rebase-merge|rebase-apply|sequencer|REVERT_HEAD|config|gk\\/config|info\\/exclude|refs\\/(?:heads|remotes|stash|tags|replace)|packed-refs|shallow)/;\n\n/**\n * Maps a path relative to a `.git` directory to the corresponding\n * {@link RepositoryChange} types. This is pure Git knowledge — the\n * regex and switch table encode which files in `.git/` correspond\n * to which logical repository changes.\n *\n * `worktrees` means the worktree list, or what `git worktree list` reports per worktree, changed:\n * `worktrees`, `worktrees/<n>` (add/remove/prune) and `worktrees/<n>/{HEAD,locked,gitdir}`. Any other\n * path under `worktrees/<n>/` (index, `*_HEAD`, `MERGE_*`, rebase state, logs, …) is that worktree's\n * own state, which its own gitdir watcher classifies, so it yields `undefined` here.\n *\n * @param relativePath - Path relative to the common `.git` directory or a worktree's gitdir\n * (e.g., `refs/heads/main`, `HEAD`, `config`, `worktrees/foo/HEAD`)\n * @returns An array of change types, or `undefined` if the path\n * is noise or unrecognized. `undefined` for `FETCH_HEAD` which\n * is intentionally not mapped to a change type (the extension\n * handles it as a last-fetched timestamp).\n */\nexport function classifyGitDirChange(relativePath: string): RepositoryChange[] | undefined {\n\t// User-edited todo file (and its backup) — handled by VS Code's TextDocument\n\t// events in the rebase webview (see `rebaseWebviewProvider.ts`). Suppress here\n\t// to avoid thrashing the repo update path on every save during an interactive\n\t// rebase; rebase lifecycle (start/stop/step) still fires from sibling files\n\t// in `rebase-merge/` and the directory itself.\n\tif (relativePath.endsWith('/git-rebase-todo') || relativePath.endsWith('/git-rebase-todo.backup')) {\n\t\treturn undefined;\n\t}\n\n\tif (relativePath.startsWith('worktrees')) {\n\t\tif (relativePath.length === 9) return ['worktrees'];\n\n\t\tif (relativePath.charCodeAt(9) === 47 /* / */) {\n\t\t\tconst idEnd = relativePath.indexOf('/', 10);\n\t\t\tif (idEnd === -1) return relativePath.length > 10 ? ['worktrees'] : undefined;\n\n\t\t\tconst file = relativePath.substring(idEnd + 1);\n\t\t\treturn file === 'HEAD' || file === 'locked' || file === 'gitdir' ? ['worktrees'] : undefined;\n\t\t}\n\t}\n\n\tconst match = classifyRegex.exec(relativePath);\n\tif (match == null) return undefined;\n\n\tswitch (match[1]) {\n\t\tcase 'config':\n\t\t\treturn ['config', 'remotes'];\n\n\t\tcase 'gk/config':\n\t\t\treturn ['gkConfig'];\n\n\t\tcase 'info/exclude':\n\t\t\treturn ['ignores'];\n\n\t\tcase 'index':\n\t\t\treturn ['index'];\n\n\t\tcase 'FETCH_HEAD':\n\t\t\t// No RepositoryChange — extension handles this for last-fetched timestamps\n\t\t\treturn undefined;\n\n\t\tcase 'HEAD':\n\t\t\treturn ['head', 'heads'];\n\n\t\tcase 'ORIG_HEAD':\n\t\t\treturn ['heads'];\n\n\t\tcase 'shallow':\n\t\tcase 'refs/replace':\n\t\t\t// Ancestry changes affect graph, blame/history, health, and ahead/behind consumers even\n\t\t\t// when tips stay put. Reuse their shared history invalidation rather than only refreshing Graph.\n\t\t\treturn ['heads'];\n\n\t\tcase 'CHERRY_PICK_HEAD':\n\t\t\treturn ['cherryPick', 'pausedOp'];\n\n\t\tcase 'MERGE_HEAD':\n\t\t\treturn ['merge', 'pausedOp'];\n\n\t\tcase 'REBASE_HEAD':\n\t\tcase 'rebase-merge':\n\t\tcase 'rebase-apply':\n\t\t\treturn ['rebase', 'pausedOp'];\n\n\t\tcase 'REVERT_HEAD':\n\t\t\treturn ['revert', 'pausedOp'];\n\n\t\tcase 'sequencer':\n\t\t\treturn ['pausedOp'];\n\n\t\t// `'heads'` is deliberately the ONLY thing a `refs/heads/*` event yields, including a create. It is\n\t\t// tempting to read a create as \"a new branch exists under this name\" and use it to drop anything\n\t\t// derived from the old branch's identity (its base, its merge target). That signal does not mean\n\t\t// what it looks like: git rewrites an EXISTING loose ref by writing `<name>.lock` and renaming it\n\t\t// over the file, which watchers report as a create of the destination — so every ordinary commit\n\t\t// would look like a new branch and discard a live branch's metadata. Nothing here can distinguish\n\t\t// the two; identity changes are handled where GitLens performs the operation itself.\n\t\tcase 'refs/heads':\n\t\t\treturn ['heads'];\n\n\t\tcase 'refs/remotes':\n\t\t\treturn ['remotes'];\n\n\t\tcase 'refs/stash':\n\t\t\treturn ['stash'];\n\n\t\tcase 'refs/tags':\n\t\t\treturn ['tags'];\n\n\t\t// A `packed-refs` rewrite (after `git pack-refs` or `git gc`) changes ref state\n\t\t// WITHOUT any `refs/**` file event — deleting a packed branch, for example, only\n\t\t// rewrites this file. The file content is not inspected here, so classification\n\t\t// is deliberately broad: it can add, remove, or move refs of any of these types.\n\t\tcase 'packed-refs':\n\t\t\treturn ['heads', 'remotes', 'tags'];\n\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n"],"mappings":";;;;;;AAOA,MAAa,8BAA2D;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;AAEA,MAAM,gBACL;;;;;;;;;;;;;;;;;;;AAoBD,SAAgB,qBAAqB,cAAsD;CAM1F,IAAI,aAAa,SAAS,kBAAkB,KAAK,aAAa,SAAS,yBAAyB,GAC/F;CAGD,IAAI,aAAa,WAAW,WAAW,GAAG;EACzC,IAAI,aAAa,WAAW,GAAG,OAAO,CAAC,WAAW;EAElD,IAAI,aAAa,WAAW,CAAC,MAAM,IAAY;GAC9C,MAAM,QAAQ,aAAa,QAAQ,KAAK,EAAE;GAC1C,IAAI,UAAU,IAAI,OAAO,aAAa,SAAS,KAAK,CAAC,WAAW,IAAI,KAAA;GAEpE,MAAM,OAAO,aAAa,UAAU,QAAQ,CAAC;GAC7C,OAAO,SAAS,UAAU,SAAS,YAAY,SAAS,WAAW,CAAC,WAAW,IAAI,KAAA;EACpF;CACD;CAEA,MAAM,QAAQ,cAAc,KAAK,YAAY;CAC7C,IAAI,SAAS,MAAM,OAAO,KAAA;CAE1B,QAAQ,MAAM,IAAd;EACC,KAAK,UACJ,OAAO,CAAC,UAAU,SAAS;EAE5B,KAAK,aACJ,OAAO,CAAC,UAAU;EAEnB,KAAK,gBACJ,OAAO,CAAC,SAAS;EAElB,KAAK,SACJ,OAAO,CAAC,OAAO;EAEhB,KAAK,cAEJ;EAED,KAAK,QACJ,OAAO,CAAC,QAAQ,OAAO;EAExB,KAAK,aACJ,OAAO,CAAC,OAAO;EAEhB,KAAK;EACL,KAAK,gBAGJ,OAAO,CAAC,OAAO;EAEhB,KAAK,oBACJ,OAAO,CAAC,cAAc,UAAU;EAEjC,KAAK,cACJ,OAAO,CAAC,SAAS,UAAU;EAE5B,KAAK;EACL,KAAK;EACL,KAAK,gBACJ,OAAO,CAAC,UAAU,UAAU;EAE7B,KAAK,eACJ,OAAO,CAAC,UAAU,UAAU;EAE7B,KAAK,aACJ,OAAO,CAAC,UAAU;EASnB,KAAK,cACJ,OAAO,CAAC,OAAO;EAEhB,KAAK,gBACJ,OAAO,CAAC,SAAS;EAElB,KAAK,cACJ,OAAO,CAAC,OAAO;EAEhB,KAAK,aACJ,OAAO,CAAC,MAAM;EAMf,KAAK,eACJ,OAAO;GAAC;GAAS;GAAW;EAAM;EAEnC,SACC;CACF;AACD"}
|
|
@@ -3,7 +3,7 @@ import { FileSystemProvider } from "../context.js";
|
|
|
3
3
|
export interface GitIgnoreFilterOptions {
|
|
4
4
|
/** Absolute path to the repository root (working tree) */
|
|
5
5
|
readonly repoPath: string;
|
|
6
|
-
/** Absolute path to the .git directory (for info/exclude) */
|
|
6
|
+
/** Absolute path to the .git directory (for info/exclude when `getInfoExcludePath` isn't provided) */
|
|
7
7
|
readonly gitDirPath: string;
|
|
8
8
|
/** File system provider for reading ignore files */
|
|
9
9
|
readonly fs: FileSystemProvider;
|
|
@@ -12,33 +12,62 @@ export interface GitIgnoreFilterOptions {
|
|
|
12
12
|
* May return undefined if not configured.
|
|
13
13
|
*/
|
|
14
14
|
readonly getGlobalExcludesPath?: () => Promise<string | undefined>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the absolute path to `info/exclude`, which lives in the COMMON git dir for a linked worktree.
|
|
17
|
+
* When provided, replaces the `gitDirPath`-based resolution; undefined means there is none to read.
|
|
18
|
+
*/
|
|
19
|
+
readonly getInfoExcludePath?: () => Promise<string | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Returns the repo-relative, `/`-separated paths of every `.gitignore` git reads (root included).
|
|
22
|
+
* Without it, only the root `.gitignore` is honoured.
|
|
23
|
+
*/
|
|
24
|
+
readonly getGitIgnorePaths?: () => Promise<readonly string[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns `core.ignorecase`, which decides whether patterns match case-insensitively. Undefined (or a failed read)
|
|
27
|
+
* falls back to the platform default (case-sensitive on Linux only).
|
|
28
|
+
*/
|
|
29
|
+
readonly getIgnoreCase?: () => Promise<boolean | undefined>;
|
|
15
30
|
}
|
|
16
31
|
/**
|
|
17
32
|
* In-memory gitignore filter using the `ignore` npm package.
|
|
18
33
|
* Fully library-owned — no VS Code dependencies.
|
|
19
34
|
*
|
|
20
|
-
* Loads patterns eagerly on creation
|
|
21
|
-
* 1.
|
|
22
|
-
* 2.
|
|
23
|
-
* 3.
|
|
35
|
+
* Loads patterns eagerly on creation, in git's precedence order (lowest first):
|
|
36
|
+
* 1. Global excludes file (`core.excludesFile`)
|
|
37
|
+
* 2. `info/exclude`
|
|
38
|
+
* 3. `<repoPath>/.gitignore`
|
|
39
|
+
* 4. Nested `.gitignore` files (via `getGitIgnorePaths`), deeper overriding shallower
|
|
24
40
|
*
|
|
25
41
|
* Once loaded, all checks are **synchronous** for maximum performance.
|
|
26
42
|
* Call `ready()` before first use to ensure patterns are loaded.
|
|
27
43
|
*/
|
|
28
44
|
export declare class GitIgnoreFilter {
|
|
29
45
|
private ig;
|
|
46
|
+
/** Matchers for nested `.gitignore` files, keyed by their repo-relative directory (no trailing slash) */
|
|
47
|
+
private nested;
|
|
48
|
+
/** The newest load, which {@link ready} waits for; cleared once it settles */
|
|
30
49
|
private loading;
|
|
50
|
+
/** The load running now; at most one runs at a time */
|
|
51
|
+
private inflight;
|
|
52
|
+
/** The one load queued behind {@link inflight}, which every refresh made meanwhile shares */
|
|
53
|
+
private trailing;
|
|
31
54
|
private readonly _generation;
|
|
55
|
+
private readonly _scratchMatchers;
|
|
56
|
+
private readonly _scratchBases;
|
|
32
57
|
private readonly repoPath;
|
|
33
58
|
private readonly gitDirPath;
|
|
34
59
|
private readonly fs;
|
|
35
60
|
private readonly getGlobalExcludesPath?;
|
|
61
|
+
private readonly getInfoExcludePath?;
|
|
62
|
+
private readonly getGitIgnorePaths?;
|
|
63
|
+
private readonly getIgnoreCase?;
|
|
36
64
|
constructor(options: GitIgnoreFilterOptions);
|
|
37
65
|
/** Resolves when patterns are loaded. Safe to call multiple times. */
|
|
38
66
|
ready(): Promise<void>;
|
|
39
67
|
/**
|
|
40
68
|
* Check if a path is ignored. Must be called after `ready()`.
|
|
41
|
-
*
|
|
69
|
+
* Errs toward "not ignored": a false "ignored" drops a real change, a false "not ignored" only costs a refresh.
|
|
70
|
+
* @param relativePath Path relative to the repository root (forward slashes; a trailing slash marks a directory)
|
|
42
71
|
* @returns true if the path should be ignored
|
|
43
72
|
*/
|
|
44
73
|
isIgnored(relativePath: string): boolean;
|
|
@@ -48,13 +77,31 @@ export declare class GitIgnoreFilter {
|
|
|
48
77
|
*/
|
|
49
78
|
filter(relativePaths: readonly string[]): string[];
|
|
50
79
|
/**
|
|
51
|
-
* Reload all patterns (e.g., after .gitignore or info/exclude changes).
|
|
52
|
-
* Returns a promise that resolves when reload is complete.
|
|
80
|
+
* Reload all patterns (e.g., after a .gitignore or info/exclude changes), rediscovering nested `.gitignore` files.
|
|
81
|
+
* Returns a promise that resolves when a reload started after this call is complete.
|
|
82
|
+
*
|
|
83
|
+
* Single-flight: an idle filter reloads at once, but while a reload runs, every further call shares one reload
|
|
84
|
+
* queued behind it — a checkout touching many `.gitignore` files costs two reloads, not one per file.
|
|
53
85
|
*/
|
|
54
86
|
refresh(): Promise<void>;
|
|
87
|
+
private startLoad;
|
|
88
|
+
/**
|
|
89
|
+
* Mirrors git's directory walk: each ancestor directory is checked shallow→deep, and the first one found ignored
|
|
90
|
+
* ignores the whole path (git never descends into it, so nothing below can re-include it). At each level, the
|
|
91
|
+
* matchers whose directory is a proper ancestor apply, and the deepest decisive one wins, falling back to the root.
|
|
92
|
+
*/
|
|
93
|
+
private isIgnoredNested;
|
|
94
|
+
/** Whether `path.slice(0, end)` is ignored, given its ancestors aren't */
|
|
95
|
+
private isLevelIgnored;
|
|
96
|
+
/** Returns the matcher's decisive verdict for `path`, or undefined when it has none */
|
|
97
|
+
private testLevel;
|
|
55
98
|
private loadPatterns;
|
|
56
|
-
|
|
57
|
-
private
|
|
99
|
+
/** Reads every nested `.gitignore`, keyed by its repo-relative directory (no trailing slash) */
|
|
100
|
+
private loadNested;
|
|
101
|
+
private readFile;
|
|
102
|
+
private readInfoExclude;
|
|
103
|
+
private readIgnoreCase;
|
|
104
|
+
private readGlobalExcludes;
|
|
58
105
|
}
|
|
59
106
|
//#endregion
|
|
60
107
|
//# sourceMappingURL=gitIgnoreFilter.d.ts.map
|