rigjs 4.0.12 → 4.0.13
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/built/index.js +154 -154
- package/lib/wiki/gitignore.ts +90 -0
- package/lib/wiki/scan.ts +0 -0
- package/lib/wiki/survey.ts +2 -17
- package/package.json +2 -2
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Multi-repo-aware .gitignore checker.
|
|
2
|
+
//
|
|
3
|
+
// Plain `git check-ignore --stdin` only knows the rules of one repo —
|
|
4
|
+
// the one its cwd lives in. When the wiki walker traverses a parent
|
|
5
|
+
// project that contains git submodules, each submodule has its OWN
|
|
6
|
+
// .gitignore (e.g. `node_modules/`) that the parent repo does NOT
|
|
7
|
+
// inherit. Running check-ignore from the parent's root therefore lets
|
|
8
|
+
// the submodule's node_modules / build/ / etc. slip through as wiki
|
|
9
|
+
// candidates — exactly the bug the user reported.
|
|
10
|
+
//
|
|
11
|
+
// Fix: for every candidate path, find its owning git repo (the nearest
|
|
12
|
+
// ancestor that has `.git` as a dir or file — submodules use a `.git`
|
|
13
|
+
// file pointing into the parent's `modules/` dir), bucket the
|
|
14
|
+
// candidates by owning repo, then run a single `git check-ignore` per
|
|
15
|
+
// bucket with cwd set to that repo's root. Each repo's own
|
|
16
|
+
// .gitignore(s) get correctly applied to the paths inside it.
|
|
17
|
+
//
|
|
18
|
+
// Paths outside any git repo are treated as "not ignored" (no rules to
|
|
19
|
+
// apply). Files whose owning repo can't process them (e.g. git binary
|
|
20
|
+
// missing) are also treated as "not ignored" — conservative, since we
|
|
21
|
+
// already have the walk-time hidden / binary-extension filters as a
|
|
22
|
+
// hard floor.
|
|
23
|
+
|
|
24
|
+
import fs from 'fs';
|
|
25
|
+
import path from 'path';
|
|
26
|
+
import { spawnSync } from 'child_process';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns a Set of the *absolute* paths that any owning git repo's
|
|
30
|
+
* .gitignore rules consider ignored.
|
|
31
|
+
*/
|
|
32
|
+
export function batchGitignored(absPaths: string[]): Set<string> {
|
|
33
|
+
const ignored = new Set<string>();
|
|
34
|
+
if (absPaths.length === 0) return ignored;
|
|
35
|
+
|
|
36
|
+
// Bucket by owning git repo. Memoize directory → repo so a deep walk
|
|
37
|
+
// doesn't re-traverse parents for every file in the same dir.
|
|
38
|
+
const dirToRepo = new Map<string, string | null>();
|
|
39
|
+
const byRepo = new Map<string, string[]>();
|
|
40
|
+
for (const abs of absPaths) {
|
|
41
|
+
const dir = path.dirname(abs);
|
|
42
|
+
let repo = dirToRepo.get(dir);
|
|
43
|
+
if (repo === undefined) {
|
|
44
|
+
repo = findGitRoot(dir);
|
|
45
|
+
dirToRepo.set(dir, repo);
|
|
46
|
+
}
|
|
47
|
+
if (!repo) continue; // outside any git repo → not ignored
|
|
48
|
+
const list = byRepo.get(repo);
|
|
49
|
+
if (list) list.push(abs);
|
|
50
|
+
else byRepo.set(repo, [abs]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const [repo, paths] of byRepo) {
|
|
54
|
+
// Pass paths as relative to the repo's root (git check-ignore
|
|
55
|
+
// accepts both, but relatives are friendlier with --stdin).
|
|
56
|
+
const rels = paths.map(p => path.relative(repo, p));
|
|
57
|
+
const r = spawnSync('git', ['check-ignore', '--stdin', '-z'], {
|
|
58
|
+
cwd: repo,
|
|
59
|
+
input: Buffer.from(rels.join('\0') + '\0'),
|
|
60
|
+
});
|
|
61
|
+
if (r.status === 128) continue; // not a git repo (shouldn't happen here)
|
|
62
|
+
if (!r.stdout || r.stdout.length === 0) continue;
|
|
63
|
+
const lines = Buffer.isBuffer(r.stdout)
|
|
64
|
+
? r.stdout.toString('utf8').split('\0')
|
|
65
|
+
: String(r.stdout).split('\0');
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
if (!line) continue;
|
|
68
|
+
ignored.add(path.resolve(repo, line));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return ignored;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Walk up from `start` looking for `.git` (either a directory for a
|
|
77
|
+
* regular repo OR a file for a submodule pointing into its parent's
|
|
78
|
+
* `modules/` storage). Returns the directory containing `.git`, or
|
|
79
|
+
* null if no ancestor has one.
|
|
80
|
+
*/
|
|
81
|
+
export function findGitRoot(start: string): string | null {
|
|
82
|
+
let dir = path.resolve(start);
|
|
83
|
+
while (true) {
|
|
84
|
+
const dotgit = path.join(dir, '.git');
|
|
85
|
+
if (fs.existsSync(dotgit)) return dir;
|
|
86
|
+
const parent = path.dirname(dir);
|
|
87
|
+
if (parent === dir) return null;
|
|
88
|
+
dir = parent;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/lib/wiki/scan.ts
CHANGED
|
Binary file
|
package/lib/wiki/survey.ts
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
import fs from 'fs';
|
|
16
16
|
import path from 'path';
|
|
17
|
-
import { spawnSync } from 'child_process';
|
|
18
17
|
import print from '../print';
|
|
19
18
|
import { requireVault, loadRigConfig, WikiEntry } from './config';
|
|
20
19
|
import { isBinaryExtension } from './fileTypes';
|
|
20
|
+
import { batchGitignored } from './gitignore';
|
|
21
21
|
import { adapters } from './agent/registry';
|
|
22
22
|
import { default as wikiIngest } from './ingest';
|
|
23
23
|
|
|
@@ -107,25 +107,10 @@ function collectCandidates(entry: WikiEntry): Candidate[] {
|
|
|
107
107
|
}
|
|
108
108
|
// Gitignore filter via batch `git check-ignore --stdin -z` (best-effort,
|
|
109
109
|
// silent fallback outside a git repo)
|
|
110
|
-
const ignored = batchGitignored(
|
|
110
|
+
const ignored = batchGitignored(out.map(c => c.abs));
|
|
111
111
|
return out.filter(c => !ignored.has(c.abs));
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function batchGitignored(root: string, abs: string[]): Set<string> {
|
|
115
|
-
const ignored = new Set<string>();
|
|
116
|
-
if (abs.length === 0) return ignored;
|
|
117
|
-
const r = spawnSync('git', ['check-ignore', '--stdin', '-z'], {
|
|
118
|
-
cwd: root,
|
|
119
|
-
input: Buffer.from(abs.join('\0') + '\0'),
|
|
120
|
-
});
|
|
121
|
-
if (r.status === 128 || !r.stdout || r.stdout.length === 0) return ignored;
|
|
122
|
-
const lines = Buffer.isBuffer(r.stdout)
|
|
123
|
-
? r.stdout.toString('utf8').split('\0')
|
|
124
|
-
: String(r.stdout).split('\0');
|
|
125
|
-
for (const line of lines) if (line) ignored.add(path.resolve(root, line));
|
|
126
|
-
return ignored;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
114
|
async function classifyWithAgent(target: WikiEntry, candidates: Candidate[]): Promise<SurveyRow[]> {
|
|
130
115
|
const rig = loadRigConfig();
|
|
131
116
|
const which = rig.wiki?.defaultAgent || 'claude';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rigjs",
|
|
3
|
-
"version": "4.0.
|
|
4
|
-
"versionCode":
|
|
3
|
+
"version": "4.0.13",
|
|
4
|
+
"versionCode": 26052419,
|
|
5
5
|
"description": "A multi-repos dev tool based on yarn and git.Rigjs is intended to be the simplest way to develop,share and deliver codes between different developers or different projects.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"modular",
|