dsh-gitnexus-plus 0.0.0-stage → 0.1.2
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/LICENSE +38 -0
- package/README.md +631 -2
- package/cordis.patch.yml +18 -0
- package/lib/bin/gitnexus-coverage.d.ts +14 -0
- package/lib/bin/gitnexus-coverage.d.ts.map +1 -0
- package/lib/bin/gitnexus-coverage.js +171 -0
- package/lib/bin/gitnexus-coverage.js.map +1 -0
- package/lib/bin/search-helper.d.ts +22 -0
- package/lib/bin/search-helper.d.ts.map +1 -0
- package/lib/bin/search-helper.js +57 -0
- package/lib/bin/search-helper.js.map +1 -0
- package/lib/client.js +2131 -0
- package/lib/gitnexus/analyze.d.ts +173 -0
- package/lib/gitnexus/analyze.d.ts.map +1 -0
- package/lib/gitnexus/analyze.js +308 -0
- package/lib/gitnexus/analyze.js.map +1 -0
- package/lib/gitnexus/commands.d.ts +129 -0
- package/lib/gitnexus/commands.d.ts.map +1 -0
- package/lib/gitnexus/commands.js +185 -0
- package/lib/gitnexus/commands.js.map +1 -0
- package/lib/gitnexus/coverage.d.ts +340 -0
- package/lib/gitnexus/coverage.d.ts.map +1 -0
- package/lib/gitnexus/coverage.js +554 -0
- package/lib/gitnexus/coverage.js.map +1 -0
- package/lib/gitnexus/format.d.ts +16 -0
- package/lib/gitnexus/format.d.ts.map +1 -0
- package/lib/gitnexus/format.js +178 -0
- package/lib/gitnexus/format.js.map +1 -0
- package/lib/gitnexus/git-activity.d.ts +136 -0
- package/lib/gitnexus/git-activity.d.ts.map +1 -0
- package/lib/gitnexus/git-activity.js +345 -0
- package/lib/gitnexus/git-activity.js.map +1 -0
- package/lib/gitnexus/git.d.ts +70 -0
- package/lib/gitnexus/git.d.ts.map +1 -0
- package/lib/gitnexus/git.js +121 -0
- package/lib/gitnexus/git.js.map +1 -0
- package/lib/gitnexus/index-meta.d.ts +160 -0
- package/lib/gitnexus/index-meta.d.ts.map +1 -0
- package/lib/gitnexus/index-meta.js +176 -0
- package/lib/gitnexus/index-meta.js.map +1 -0
- package/lib/gitnexus/install.d.ts +97 -0
- package/lib/gitnexus/install.d.ts.map +1 -0
- package/lib/gitnexus/install.js +228 -0
- package/lib/gitnexus/install.js.map +1 -0
- package/lib/gitnexus/languages.d.ts +80 -0
- package/lib/gitnexus/languages.d.ts.map +1 -0
- package/lib/gitnexus/languages.js +297 -0
- package/lib/gitnexus/languages.js.map +1 -0
- package/lib/gitnexus/root.d.ts +74 -0
- package/lib/gitnexus/root.d.ts.map +1 -0
- package/lib/gitnexus/root.js +168 -0
- package/lib/gitnexus/root.js.map +1 -0
- package/lib/gitnexus/scan.d.ts +68 -0
- package/lib/gitnexus/scan.d.ts.map +1 -0
- package/lib/gitnexus/scan.js +249 -0
- package/lib/gitnexus/scan.js.map +1 -0
- package/lib/gitnexus/search.d.ts +167 -0
- package/lib/gitnexus/search.d.ts.map +1 -0
- package/lib/gitnexus/search.js +517 -0
- package/lib/gitnexus/search.js.map +1 -0
- package/lib/gitnexus/toolchain.d.ts +136 -0
- package/lib/gitnexus/toolchain.d.ts.map +1 -0
- package/lib/gitnexus/toolchain.js +251 -0
- package/lib/gitnexus/toolchain.js.map +1 -0
- package/lib/index.d.ts +98 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +252 -0
- package/lib/index.js.map +1 -0
- package/lib/routes/analyze.d.ts +41 -0
- package/lib/routes/analyze.d.ts.map +1 -0
- package/lib/routes/analyze.js +75 -0
- package/lib/routes/analyze.js.map +1 -0
- package/lib/routes/coverage.d.ts +52 -0
- package/lib/routes/coverage.d.ts.map +1 -0
- package/lib/routes/coverage.js +81 -0
- package/lib/routes/coverage.js.map +1 -0
- package/lib/routes/guard.d.ts +92 -0
- package/lib/routes/guard.d.ts.map +1 -0
- package/lib/routes/guard.js +187 -0
- package/lib/routes/guard.js.map +1 -0
- package/lib/routes/install.d.ts +27 -0
- package/lib/routes/install.d.ts.map +1 -0
- package/lib/routes/install.js +46 -0
- package/lib/routes/install.js.map +1 -0
- package/lib/routes/search.d.ts +27 -0
- package/lib/routes/search.d.ts.map +1 -0
- package/lib/routes/search.js +77 -0
- package/lib/routes/search.js.map +1 -0
- package/package.json +87 -4
- package/scripts/link-runtime.mjs +146 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locate the installed GitNexus package and reuse its own scan primitives.
|
|
3
|
+
*
|
|
4
|
+
* WHY REUSE INSTEAD OF REIMPLEMENT
|
|
5
|
+
* --------------------------------
|
|
6
|
+
* "Which files did GitNexus skip?" has exactly one correct answer: the set
|
|
7
|
+
* `walkRepositoryPaths` produced during `analyze`. Reimplementing that decision
|
|
8
|
+
* here would drift from it silently — the plugin would report a large-file list
|
|
9
|
+
* that no longer matches the index, and nothing would fail loudly.
|
|
10
|
+
*
|
|
11
|
+
* `gitnexus/package.json` declares no `exports` map, so its `dist/**` files are
|
|
12
|
+
* deep-importable. That is what makes reuse possible; it is also why every entry
|
|
13
|
+
* point below is guarded. If a future release closes the exports map or renames a
|
|
14
|
+
* module, `loadScanPrimitives` returns `null` and the caller falls back to the
|
|
15
|
+
* local scan (`./scan-fallback.js`) rather than throwing.
|
|
16
|
+
*/
|
|
17
|
+
/** What a caller may say about where to look for the installed package. */
|
|
18
|
+
export interface RootDiscoveryOptions {
|
|
19
|
+
env?: NodeJS.ProcessEnv;
|
|
20
|
+
moduleUrl?: string;
|
|
21
|
+
discover?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The prefix a panel-authorised install wrote to. Consulted before PATH and the
|
|
24
|
+
* declared dependency, because it is the only copy whose version the plugin
|
|
25
|
+
* chose — and, after an install from the panel, the only copy on the machine.
|
|
26
|
+
*/
|
|
27
|
+
managedPrefix?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the GitNexus package root, or `null` when no usable install is found.
|
|
31
|
+
*/
|
|
32
|
+
export declare function findGitnexusRoot(options?: RootDiscoveryOptions): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Read the installed GitNexus version. Returned for provenance so a report can
|
|
35
|
+
* state which analyzer produced the index it is judging.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readGitnexusVersion(root: string): string | null;
|
|
38
|
+
/** `walkRepositoryPaths(repoPath, onProgress?, options?)` — GitNexus's own walk. */
|
|
39
|
+
export type WalkRepositoryPaths = (repoPath: string, onProgress?: unknown, options?: object) => Promise<Array<{
|
|
40
|
+
path: string;
|
|
41
|
+
size: number;
|
|
42
|
+
}>>;
|
|
43
|
+
/** `createIgnoreFilter(repoPath, options?)` — the matcher `glob` is handed. */
|
|
44
|
+
export type CreateIgnoreFilter = (repoPath: string, options?: object) => Promise<unknown>;
|
|
45
|
+
/** The slice of the `glob` package this plugin calls. */
|
|
46
|
+
export type GlobFunction = (pattern: string, options: object) => Promise<string[]>;
|
|
47
|
+
/**
|
|
48
|
+
* The scan primitives this plugin reuses, all sourced from one GitNexus install.
|
|
49
|
+
*/
|
|
50
|
+
export interface ScanPrimitives {
|
|
51
|
+
gitnexusRoot: string;
|
|
52
|
+
gitnexusVersion: string | null;
|
|
53
|
+
glob: GlobFunction;
|
|
54
|
+
createIgnoreFilter: CreateIgnoreFilter;
|
|
55
|
+
walkRepositoryPaths: WalkRepositoryPaths;
|
|
56
|
+
getMaxFileSizeBytes: () => number;
|
|
57
|
+
DEFAULT_MAX_FILE_SIZE_BYTES: number;
|
|
58
|
+
MAX_FILE_SIZE_UPPER_BOUND_BYTES: number;
|
|
59
|
+
source: 'gitnexus' | 'fallback';
|
|
60
|
+
}
|
|
61
|
+
/** What a caller may override when loading the primitives. */
|
|
62
|
+
export interface LoadScanPrimitivesOptions extends RootDiscoveryOptions {
|
|
63
|
+
root?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Load GitNexus's own scan primitives by deep-importing its dist modules.
|
|
67
|
+
*
|
|
68
|
+
* Every exported member is validated before use: a partial or reshaped module
|
|
69
|
+
* degrades to the fallback rather than producing a wrong answer.
|
|
70
|
+
*
|
|
71
|
+
* @returns `null` when reuse is not possible.
|
|
72
|
+
*/
|
|
73
|
+
export declare function loadScanPrimitives(options?: LoadScanPrimitivesOptions): Promise<ScanPrimitives | null>;
|
|
74
|
+
//# sourceMappingURL=root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA4DD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,GAAG,IAAI,CAWlF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS/D;AAKD,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1F,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AA6BnF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAClC,2BAA2B,EAAE,MAAM,CAAC;IACpC,+BAA+B,EAAE,MAAM,CAAC;IACxC,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC;AAED,8DAA8D;AAC9D,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAiDhC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locate the installed GitNexus package and reuse its own scan primitives.
|
|
3
|
+
*
|
|
4
|
+
* WHY REUSE INSTEAD OF REIMPLEMENT
|
|
5
|
+
* --------------------------------
|
|
6
|
+
* "Which files did GitNexus skip?" has exactly one correct answer: the set
|
|
7
|
+
* `walkRepositoryPaths` produced during `analyze`. Reimplementing that decision
|
|
8
|
+
* here would drift from it silently — the plugin would report a large-file list
|
|
9
|
+
* that no longer matches the index, and nothing would fail loudly.
|
|
10
|
+
*
|
|
11
|
+
* `gitnexus/package.json` declares no `exports` map, so its `dist/**` files are
|
|
12
|
+
* deep-importable. That is what makes reuse possible; it is also why every entry
|
|
13
|
+
* point below is guarded. If a future release closes the exports map or renames a
|
|
14
|
+
* module, `loadScanPrimitives` returns `null` and the caller falls back to the
|
|
15
|
+
* local scan (`./scan-fallback.js`) rather than throwing.
|
|
16
|
+
*/
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
18
|
+
import { pathToFileURL } from 'node:url';
|
|
19
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
/** Deep paths inside the `gitnexus` package that this plugin depends on. */
|
|
22
|
+
const DIST = Object.freeze({
|
|
23
|
+
walker: 'dist/core/ingestion/filesystem-walker.js',
|
|
24
|
+
maxFileSize: 'dist/core/ingestion/utils/max-file-size.js',
|
|
25
|
+
ignore: 'dist/config/ignore-service.js',
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Candidate directories that may contain an installed `gitnexus` package.
|
|
29
|
+
* Ordered most-specific first: an explicit override beats PATH discovery, which
|
|
30
|
+
* beats a plain resolution from this package.
|
|
31
|
+
*
|
|
32
|
+
* Discovery always consults the real process environment for `PATH`, even when a
|
|
33
|
+
* caller passes its own `env`. The `env` option governs *configuration*
|
|
34
|
+
* (`GITNEXUS_MAX_FILE_SIZE`, `GITNEXUS_HOME`); which GitNexus is installed on this
|
|
35
|
+
* machine is a fact about the machine, not a per-call setting, and letting a
|
|
36
|
+
* sanitized env blank it out would silently downgrade every caller to the
|
|
37
|
+
* fallback scan.
|
|
38
|
+
*
|
|
39
|
+
* @returns absolute candidate directories (not yet validated)
|
|
40
|
+
*/
|
|
41
|
+
function candidateRoots(options = {}) {
|
|
42
|
+
if (options.discover === false)
|
|
43
|
+
return [];
|
|
44
|
+
const env = { ...process.env, ...(options.env ?? {}) };
|
|
45
|
+
const roots = [];
|
|
46
|
+
if (env.GITNEXUS_PACKAGE_ROOT)
|
|
47
|
+
roots.push(env.GITNEXUS_PACKAGE_ROOT);
|
|
48
|
+
// The copy this plugin installed. Ahead of PATH and the dependency because it is
|
|
49
|
+
// the version the operator selected by installing; finding a different one later
|
|
50
|
+
// would make the report describe a tree the refresh will not use.
|
|
51
|
+
if (typeof options.managedPrefix === 'string' && options.managedPrefix !== '') {
|
|
52
|
+
roots.push(path.join(options.managedPrefix, 'node_modules', 'gitnexus'));
|
|
53
|
+
}
|
|
54
|
+
// Probe every PATH entry for a sibling `node_modules/gitnexus` directly.
|
|
55
|
+
//
|
|
56
|
+
// Deliberately NOT "find the gitnexus shim, then derive its prefix": the shim
|
|
57
|
+
// is `.ps1` under nvm4w, and `PATHEXT` on Windows does not list `.ps1`, so
|
|
58
|
+
// shim-based discovery silently finds nothing on the very machines where the
|
|
59
|
+
// CLI is most likely to be installed. Testing the directory is
|
|
60
|
+
// extension-independent and needs no PATHEXT reasoning.
|
|
61
|
+
for (const dir of (env.PATH ?? '').split(path.delimiter)) {
|
|
62
|
+
if (dir === '')
|
|
63
|
+
continue;
|
|
64
|
+
roots.push(path.join(dir, 'node_modules', 'gitnexus'));
|
|
65
|
+
roots.push(path.join(dir, '..', 'node_modules', 'gitnexus'));
|
|
66
|
+
roots.push(path.join(dir, '..', '..', 'node_modules', 'gitnexus'));
|
|
67
|
+
}
|
|
68
|
+
// nvm-for-windows keeps the real tree off PATH behind a junction.
|
|
69
|
+
if (env.NVM_SYMLINK)
|
|
70
|
+
roots.push(path.join(env.NVM_SYMLINK, 'node_modules', 'gitnexus'));
|
|
71
|
+
if (env.NVM_HOME)
|
|
72
|
+
roots.push(path.join(env.NVM_HOME, 'node_modules', 'gitnexus'));
|
|
73
|
+
// Resolve from this package (a real dependency edge, if declared).
|
|
74
|
+
try {
|
|
75
|
+
const here = options.moduleUrl ? path.dirname(new URL(options.moduleUrl).pathname.replace(/^\/([A-Za-z]:)/, '$1')) : undefined;
|
|
76
|
+
const req = createRequire(here ? path.join(here, 'noop.js') : import.meta.url);
|
|
77
|
+
roots.push(path.dirname(req.resolve('gitnexus/package.json')));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* not resolvable from here — the other candidates may still work */
|
|
81
|
+
}
|
|
82
|
+
return [...new Set(roots.map((r) => path.resolve(r)))];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the GitNexus package root, or `null` when no usable install is found.
|
|
86
|
+
*/
|
|
87
|
+
export function findGitnexusRoot(options = {}) {
|
|
88
|
+
for (const root of candidateRoots(options)) {
|
|
89
|
+
try {
|
|
90
|
+
if (existsSync(path.join(root, 'package.json')) && existsSync(path.join(root, DIST.walker))) {
|
|
91
|
+
return root;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
/* unreadable candidate — keep looking */
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Read the installed GitNexus version. Returned for provenance so a report can
|
|
102
|
+
* state which analyzer produced the index it is judging.
|
|
103
|
+
*/
|
|
104
|
+
export function readGitnexusVersion(root) {
|
|
105
|
+
try {
|
|
106
|
+
const pkg = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
107
|
+
return typeof pkg.version === 'string' ? pkg.version : null;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** The URL a deep-imported `dist` module is loaded from. */
|
|
114
|
+
const distUrl = (root, relative) => pathToFileURL(path.join(root, relative)).href;
|
|
115
|
+
/**
|
|
116
|
+
* Load GitNexus's own scan primitives by deep-importing its dist modules.
|
|
117
|
+
*
|
|
118
|
+
* Every exported member is validated before use: a partial or reshaped module
|
|
119
|
+
* degrades to the fallback rather than producing a wrong answer.
|
|
120
|
+
*
|
|
121
|
+
* @returns `null` when reuse is not possible.
|
|
122
|
+
*/
|
|
123
|
+
export async function loadScanPrimitives(options = {}) {
|
|
124
|
+
const root = options.root ?? findGitnexusRoot(options);
|
|
125
|
+
if (root === null)
|
|
126
|
+
return null;
|
|
127
|
+
try {
|
|
128
|
+
const [walker, maxSize, ignore] = await Promise.all([
|
|
129
|
+
import(distUrl(root, DIST.walker)),
|
|
130
|
+
import(distUrl(root, DIST.maxFileSize)),
|
|
131
|
+
import(distUrl(root, DIST.ignore)),
|
|
132
|
+
]);
|
|
133
|
+
const createIgnoreFilter = ignore.createIgnoreFilter;
|
|
134
|
+
const walkRepositoryPaths = walker.walkRepositoryPaths;
|
|
135
|
+
const getMaxFileSizeBytes = maxSize.getMaxFileSizeBytes;
|
|
136
|
+
const DEFAULT_MAX_FILE_SIZE_BYTES = maxSize.DEFAULT_MAX_FILE_SIZE_BYTES;
|
|
137
|
+
if (typeof createIgnoreFilter !== 'function' ||
|
|
138
|
+
typeof walkRepositoryPaths !== 'function' ||
|
|
139
|
+
typeof getMaxFileSizeBytes !== 'function' ||
|
|
140
|
+
typeof DEFAULT_MAX_FILE_SIZE_BYTES !== 'number') {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// `glob` is resolved from GitNexus's own dependency tree so the version that
|
|
144
|
+
// built the ignore filter is the version that consumes it.
|
|
145
|
+
const req = createRequire(path.join(root, 'package.json'));
|
|
146
|
+
const globModule = (await import(pathToFileURL(req.resolve('glob')).href));
|
|
147
|
+
const glob = globModule.glob ?? globModule.default?.glob ?? globModule.default;
|
|
148
|
+
if (typeof glob !== 'function')
|
|
149
|
+
return null;
|
|
150
|
+
return {
|
|
151
|
+
gitnexusRoot: root,
|
|
152
|
+
gitnexusVersion: readGitnexusVersion(root),
|
|
153
|
+
glob,
|
|
154
|
+
createIgnoreFilter,
|
|
155
|
+
walkRepositoryPaths,
|
|
156
|
+
getMaxFileSizeBytes,
|
|
157
|
+
DEFAULT_MAX_FILE_SIZE_BYTES,
|
|
158
|
+
MAX_FILE_SIZE_UPPER_BOUND_BYTES: typeof maxSize.MAX_FILE_SIZE_UPPER_BOUND_BYTES === 'number'
|
|
159
|
+
? maxSize.MAX_FILE_SIZE_UPPER_BOUND_BYTES
|
|
160
|
+
: DEFAULT_MAX_FILE_SIZE_BYTES,
|
|
161
|
+
source: 'gitnexus',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reproduce GitNexus's scan decision and expose what it discards.
|
|
3
|
+
*
|
|
4
|
+
* `walkRepositoryPaths` (gitnexus/dist/core/ingestion/filesystem-walker.js)
|
|
5
|
+
* makes three cuts and only returns the survivors:
|
|
6
|
+
*
|
|
7
|
+
* 1. `glob(recursive, { nodir: true, dot: false, ignore: createIgnoreFilter(repo) })`
|
|
8
|
+
* — drops dotfiles (`dot: false`) and anything the ignore rules match.
|
|
9
|
+
* 2. `stat.size > maxFileSizeBytes` — the large-file cut. **Counted and logged
|
|
10
|
+
* but never returned**, so an external tool cannot see it.
|
|
11
|
+
* 3. `.d.ts` / `.d.mts` / `.d.cts` whose same-stem implementation was also
|
|
12
|
+
* scanned — suppressed as redundant.
|
|
13
|
+
*
|
|
14
|
+
* This module applies cuts 1 and 3 exactly as upstream does (reusing upstream's
|
|
15
|
+
* own `createIgnoreFilter` and glob), and turns cut 2 — the one that is invisible
|
|
16
|
+
* from outside — into data.
|
|
17
|
+
*
|
|
18
|
+
* Deliberate duplication: the single `glob(...)` call below mirrors
|
|
19
|
+
* `filesystem-walker.js:62-67`. It is four lines and must stay in lockstep with
|
|
20
|
+
* upstream. If it ever drifts, `test/run.mjs` catches it by cross-checking the
|
|
21
|
+
* reported large-file count against what `analyze` itself prints.
|
|
22
|
+
*/
|
|
23
|
+
import { type ScanPrimitives } from './root.js';
|
|
24
|
+
/** One file the scan walked. */
|
|
25
|
+
export interface ScannedFile {
|
|
26
|
+
/** repo-relative, forward slashes */
|
|
27
|
+
path: string;
|
|
28
|
+
/** bytes */
|
|
29
|
+
size: number;
|
|
30
|
+
}
|
|
31
|
+
/** Where the effective size cap came from. */
|
|
32
|
+
export type CapSource = 'env' | 'default' | 'index';
|
|
33
|
+
/** What {@link scanRepository} reports: the survivors plus all three cuts as data. */
|
|
34
|
+
export interface ScanReport {
|
|
35
|
+
/** files GitNexus would hand to the pipeline */
|
|
36
|
+
selected: ScannedFile[];
|
|
37
|
+
/** files dropped by the size cap, largest first */
|
|
38
|
+
large: ScannedFile[];
|
|
39
|
+
/** `.d.ts` dropped as redundant */
|
|
40
|
+
suppressedDeclarations: ScannedFile[];
|
|
41
|
+
/** files that survived the ignore/dotfile cut */
|
|
42
|
+
scannedCount: number;
|
|
43
|
+
/** the effective size cap */
|
|
44
|
+
capBytes: number;
|
|
45
|
+
/** the shipped default */
|
|
46
|
+
defaultCapBytes: number;
|
|
47
|
+
/** where the effective cap came from */
|
|
48
|
+
capSource: CapSource;
|
|
49
|
+
/** hard tree-sitter ceiling */
|
|
50
|
+
maxCapBytes: number;
|
|
51
|
+
gitnexusVersion: string;
|
|
52
|
+
/** reused upstream primitives or a local glob */
|
|
53
|
+
primitives: 'gitnexus' | 'fallback';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Scan a repository the way GitNexus does, and report the size cut as data.
|
|
57
|
+
*
|
|
58
|
+
* @param repoPath absolute path to the repository root
|
|
59
|
+
* @param options `capBytes` overrides the cap (used when the index records its own coverage
|
|
60
|
+
* policy); otherwise `GITNEXUS_MAX_FILE_SIZE` decides, as it does for `analyze`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function scanRepository(repoPath: string, options?: {
|
|
63
|
+
capBytes?: number;
|
|
64
|
+
env?: NodeJS.ProcessEnv;
|
|
65
|
+
primitives?: ScanPrimitives | null;
|
|
66
|
+
managedPrefix?: string;
|
|
67
|
+
}): Promise<ScanReport>;
|
|
68
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/gitnexus/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAkBpE,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,mCAAmC;IACnC,sBAAsB,EAAE,WAAW,EAAE,CAAC;IACtC,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,SAAS,EAAE,SAAS,CAAC;IACrB,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC;CACrC;AA6CD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACnB,GACL,OAAO,CAAC,UAAU,CAAC,CAkErB"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reproduce GitNexus's scan decision and expose what it discards.
|
|
3
|
+
*
|
|
4
|
+
* `walkRepositoryPaths` (gitnexus/dist/core/ingestion/filesystem-walker.js)
|
|
5
|
+
* makes three cuts and only returns the survivors:
|
|
6
|
+
*
|
|
7
|
+
* 1. `glob(recursive, { nodir: true, dot: false, ignore: createIgnoreFilter(repo) })`
|
|
8
|
+
* — drops dotfiles (`dot: false`) and anything the ignore rules match.
|
|
9
|
+
* 2. `stat.size > maxFileSizeBytes` — the large-file cut. **Counted and logged
|
|
10
|
+
* but never returned**, so an external tool cannot see it.
|
|
11
|
+
* 3. `.d.ts` / `.d.mts` / `.d.cts` whose same-stem implementation was also
|
|
12
|
+
* scanned — suppressed as redundant.
|
|
13
|
+
*
|
|
14
|
+
* This module applies cuts 1 and 3 exactly as upstream does (reusing upstream's
|
|
15
|
+
* own `createIgnoreFilter` and glob), and turns cut 2 — the one that is invisible
|
|
16
|
+
* from outside — into data.
|
|
17
|
+
*
|
|
18
|
+
* Deliberate duplication: the single `glob(...)` call below mirrors
|
|
19
|
+
* `filesystem-walker.js:62-67`. It is four lines and must stay in lockstep with
|
|
20
|
+
* upstream. If it ever drifts, `test/run.mjs` catches it by cross-checking the
|
|
21
|
+
* reported large-file count against what `analyze` itself prints.
|
|
22
|
+
*/
|
|
23
|
+
import fs from 'node:fs/promises';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
import { loadScanPrimitives } from './root.js';
|
|
26
|
+
/** Mirrors DECLARATION_COMPANION_SUFFIXES in filesystem-walker.js. */
|
|
27
|
+
const DECLARATION_COMPANION_SUFFIXES = Object.freeze([
|
|
28
|
+
{ declaration: '.d.ts', implementations: ['.ts', '.tsx'] },
|
|
29
|
+
{ declaration: '.d.mts', implementations: ['.mts'] },
|
|
30
|
+
{ declaration: '.d.cts', implementations: ['.cts'] },
|
|
31
|
+
]);
|
|
32
|
+
/** Bounded concurrency for `fs.stat`, matching GitNexus's READ_CONCURRENCY. */
|
|
33
|
+
const STAT_CONCURRENCY = 32;
|
|
34
|
+
/**
|
|
35
|
+
* @returns entries minus redundant declaration files
|
|
36
|
+
*/
|
|
37
|
+
function dropRedundantDeclarations(entries) {
|
|
38
|
+
const scannedPaths = new Set(entries.map((e) => e.path));
|
|
39
|
+
return entries.filter((entry) => {
|
|
40
|
+
const companion = DECLARATION_COMPANION_SUFFIXES.find(({ declaration }) => entry.path.endsWith(declaration));
|
|
41
|
+
if (!companion)
|
|
42
|
+
return true;
|
|
43
|
+
const stem = entry.path.slice(0, -companion.declaration.length);
|
|
44
|
+
const redundant = companion.implementations.some((suffix) => scannedPaths.has(`${stem}${suffix}`));
|
|
45
|
+
return !redundant;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function redundantDeclarations(entries, selectedPaths) {
|
|
49
|
+
const kept = new Set(selectedPaths);
|
|
50
|
+
return entries.filter((e) => !kept.has(e.path));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Run a batched `fs.stat` over repo-relative paths.
|
|
54
|
+
* Unreadable files are skipped rather than failing the scan: a file that
|
|
55
|
+
* disappears mid-scan is normal, not an error.
|
|
56
|
+
*/
|
|
57
|
+
async function statAll(repoPath, relativePaths) {
|
|
58
|
+
const out = [];
|
|
59
|
+
for (let i = 0; i < relativePaths.length; i += STAT_CONCURRENCY) {
|
|
60
|
+
const batch = relativePaths.slice(i, i + STAT_CONCURRENCY);
|
|
61
|
+
const settled = await Promise.allSettled(batch.map(async (relativePath) => {
|
|
62
|
+
const stat = await fs.stat(path.join(repoPath, relativePath));
|
|
63
|
+
return { path: relativePath.replace(/\\/g, '/'), size: stat.size };
|
|
64
|
+
}));
|
|
65
|
+
for (const result of settled) {
|
|
66
|
+
if (result.status === 'fulfilled')
|
|
67
|
+
out.push(result.value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Scan a repository the way GitNexus does, and report the size cut as data.
|
|
74
|
+
*
|
|
75
|
+
* @param repoPath absolute path to the repository root
|
|
76
|
+
* @param options `capBytes` overrides the cap (used when the index records its own coverage
|
|
77
|
+
* policy); otherwise `GITNEXUS_MAX_FILE_SIZE` decides, as it does for `analyze`.
|
|
78
|
+
*/
|
|
79
|
+
export async function scanRepository(repoPath, options = {}) {
|
|
80
|
+
const env = options.env ?? process.env;
|
|
81
|
+
const primitives = options.primitives === undefined
|
|
82
|
+
? await loadScanPrimitives({ env, managedPrefix: options.managedPrefix })
|
|
83
|
+
: options.primitives;
|
|
84
|
+
const defaultCapBytes = primitives?.DEFAULT_MAX_FILE_SIZE_BYTES ?? 512 * 1024;
|
|
85
|
+
const maxCapBytes = primitives?.MAX_FILE_SIZE_UPPER_BOUND_BYTES ?? 32 * 1024 * 1024;
|
|
86
|
+
let capBytes;
|
|
87
|
+
let capSource;
|
|
88
|
+
if (typeof options.capBytes === 'number' && Number.isFinite(options.capBytes) && options.capBytes > 0) {
|
|
89
|
+
capBytes = Math.min(options.capBytes, maxCapBytes);
|
|
90
|
+
capSource = 'index';
|
|
91
|
+
}
|
|
92
|
+
else if (primitives) {
|
|
93
|
+
capBytes = Math.min(primitives.getMaxFileSizeBytes(), maxCapBytes);
|
|
94
|
+
capSource = env.GITNEXUS_MAX_FILE_SIZE ? 'env' : 'default';
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const parsed = Number(env.GITNEXUS_MAX_FILE_SIZE);
|
|
98
|
+
const valid = Number.isInteger(parsed) && parsed > 0;
|
|
99
|
+
capBytes = valid ? Math.min(parsed * 1024, maxCapBytes) : defaultCapBytes;
|
|
100
|
+
capSource = valid ? 'env' : 'default';
|
|
101
|
+
}
|
|
102
|
+
let matched;
|
|
103
|
+
if (primitives) {
|
|
104
|
+
// Upstream's own filter and glob options, verbatim.
|
|
105
|
+
const ignoreFilter = await primitives.createIgnoreFilter(repoPath);
|
|
106
|
+
matched = await primitives.glob('**/*', {
|
|
107
|
+
cwd: repoPath,
|
|
108
|
+
nodir: true,
|
|
109
|
+
dot: false,
|
|
110
|
+
ignore: ignoreFilter,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
matched = await fallbackWalk(repoPath);
|
|
115
|
+
}
|
|
116
|
+
const scanned = await statAll(repoPath, matched);
|
|
117
|
+
scanned.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
118
|
+
const large = [];
|
|
119
|
+
const withinCap = [];
|
|
120
|
+
for (const file of scanned) {
|
|
121
|
+
if (file.size > capBytes)
|
|
122
|
+
large.push(file);
|
|
123
|
+
else
|
|
124
|
+
withinCap.push(file);
|
|
125
|
+
}
|
|
126
|
+
const selected = dropRedundantDeclarations(withinCap);
|
|
127
|
+
const suppressed = redundantDeclarations(withinCap, selected.map((f) => f.path));
|
|
128
|
+
large.sort((a, b) => b.size - a.size || (a.path < b.path ? -1 : 1));
|
|
129
|
+
return {
|
|
130
|
+
selected,
|
|
131
|
+
large,
|
|
132
|
+
suppressedDeclarations: suppressed,
|
|
133
|
+
scannedCount: scanned.length,
|
|
134
|
+
capBytes,
|
|
135
|
+
defaultCapBytes,
|
|
136
|
+
capSource,
|
|
137
|
+
maxCapBytes,
|
|
138
|
+
gitnexusVersion: primitives?.gitnexusVersion ?? 'unknown',
|
|
139
|
+
primitives: primitives ? 'gitnexus' : 'fallback',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Minimal `.gitignore`-style matcher used **only** when GitNexus's ignore service
|
|
144
|
+
* cannot be loaded.
|
|
145
|
+
*
|
|
146
|
+
* This is an approximation and is labelled as one wherever it surfaces
|
|
147
|
+
* (`ScanReport.primitives === 'fallback'`). It deliberately does not implement
|
|
148
|
+
* negation: refusing to un-ignore a file can over-report exclusions, whereas
|
|
149
|
+
* honouring `!` incorrectly would under-report skipped large files — and the
|
|
150
|
+
* second error is the one this tool exists to prevent.
|
|
151
|
+
*
|
|
152
|
+
* @param pattern a gitignore line, already trimmed
|
|
153
|
+
*/
|
|
154
|
+
function compileIgnorePattern(pattern) {
|
|
155
|
+
const cleaned = pattern.replace(/^\//, '').replace(/\/+$/, '');
|
|
156
|
+
const parts = cleaned.split('/').filter((p) => p !== '');
|
|
157
|
+
const toSegmentRegex = (segment) => new RegExp(`^${segment.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*').replace(/\?/g, '[^/]')}$`, 'i');
|
|
158
|
+
return (segments) => {
|
|
159
|
+
// A pattern with no slash matches a basename at any depth; a pattern with one
|
|
160
|
+
// is anchored to the repository root (gitignore's own rule).
|
|
161
|
+
if (parts.length === 1) {
|
|
162
|
+
const re = toSegmentRegex(parts[0]);
|
|
163
|
+
return segments.some((s) => re.test(s));
|
|
164
|
+
}
|
|
165
|
+
// `**` spans any number of segments; expand it greedily by simple recursion.
|
|
166
|
+
const matchFrom = (pi, si) => {
|
|
167
|
+
if (pi === parts.length)
|
|
168
|
+
return true;
|
|
169
|
+
if (si > segments.length)
|
|
170
|
+
return false;
|
|
171
|
+
if (parts[pi] === '**') {
|
|
172
|
+
for (let skip = si; skip <= segments.length; skip += 1) {
|
|
173
|
+
if (matchFrom(pi + 1, skip))
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
if (si === segments.length)
|
|
179
|
+
return false;
|
|
180
|
+
return toSegmentRegex(parts[pi]).test(segments[si]) && matchFrom(pi + 1, si + 1);
|
|
181
|
+
};
|
|
182
|
+
return parts[0] === '**' ? matchFrom(0, 0) : matchFrom(0, 0);
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Read `.gitignore` and `.gitnexusignore` into predicates, plus the two
|
|
187
|
+
* directories GitNexus always ignores.
|
|
188
|
+
*/
|
|
189
|
+
async function loadFallbackRules(repoPath) {
|
|
190
|
+
const matchers = [compileIgnorePattern('node_modules'), compileIgnorePattern('.git')];
|
|
191
|
+
for (const name of ['.gitignore', '.gitnexusignore']) {
|
|
192
|
+
let text;
|
|
193
|
+
try {
|
|
194
|
+
text = await fs.readFile(path.join(repoPath, name), 'utf8');
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
200
|
+
const line = raw.trim();
|
|
201
|
+
if (line === '' || line.startsWith('#') || line.startsWith('!'))
|
|
202
|
+
continue;
|
|
203
|
+
matchers.push(compileIgnorePattern(line));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return matchers;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Dependency-free fallback walk, used only when GitNexus's `glob` cannot be
|
|
210
|
+
* resolved. Mirrors two upstream behaviours that are easy to get wrong:
|
|
211
|
+
*
|
|
212
|
+
* - `dot: false` — a path is excluded when *any* segment begins with `.`,
|
|
213
|
+
* which is why `.github/workflows/ci.yml` never reaches the pipeline.
|
|
214
|
+
* - directories matched by the ignore rules prune their whole subtree.
|
|
215
|
+
*
|
|
216
|
+
* @returns repo-relative paths, forward slashes
|
|
217
|
+
*/
|
|
218
|
+
async function fallbackWalk(repoPath) {
|
|
219
|
+
const rules = await loadFallbackRules(repoPath);
|
|
220
|
+
const ignored = (segments) => rules.some((rule) => rule(segments));
|
|
221
|
+
const out = [];
|
|
222
|
+
const queue = [{ abs: repoPath, rel: [] }];
|
|
223
|
+
while (queue.length > 0) {
|
|
224
|
+
const dir = queue.pop();
|
|
225
|
+
let entries;
|
|
226
|
+
try {
|
|
227
|
+
entries = await fs.readdir(dir.abs, { withFileTypes: true });
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
for (const entry of entries) {
|
|
233
|
+
if (entry.name.startsWith('.'))
|
|
234
|
+
continue; // dot: false
|
|
235
|
+
const segments = [...dir.rel, entry.name];
|
|
236
|
+
if (ignored(segments))
|
|
237
|
+
continue;
|
|
238
|
+
const abs = path.join(dir.abs, entry.name);
|
|
239
|
+
if (entry.isDirectory()) {
|
|
240
|
+
queue.push({ abs, rel: segments });
|
|
241
|
+
}
|
|
242
|
+
else if (entry.isFile()) {
|
|
243
|
+
out.push(segments.join('/'));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/gitnexus/scan.ts"],"names":[],"mappings":"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"}
|