chivgent 0.6.0 → 0.7.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/README.md +35 -8
- package/README.zh-CN.md +32 -8
- package/dist/cli-options.d.ts +8 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +16 -2
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +20 -3
- package/dist/cli.js.map +1 -1
- package/dist/tools/edit-file.d.ts +26 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +72 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/write-file.d.ts +22 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +59 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/workspace/ignore.d.ts +6 -0
- package/dist/workspace/ignore.d.ts.map +1 -0
- package/dist/workspace/ignore.js +35 -0
- package/dist/workspace/ignore.js.map +1 -0
- package/dist/workspace/list.d.ts +3 -0
- package/dist/workspace/list.d.ts.map +1 -0
- package/dist/workspace/list.js +63 -0
- package/dist/workspace/list.js.map +1 -0
- package/dist/workspace/paths.d.ts +41 -0
- package/dist/workspace/paths.d.ts.map +1 -0
- package/dist/workspace/paths.js +189 -0
- package/dist/workspace/paths.js.map +1 -0
- package/dist/workspace/read.d.ts +4 -0
- package/dist/workspace/read.d.ts.map +1 -0
- package/dist/workspace/read.js +37 -0
- package/dist/workspace/read.js.map +1 -0
- package/dist/workspace/search.d.ts +3 -0
- package/dist/workspace/search.d.ts.map +1 -0
- package/dist/workspace/search.js +134 -0
- package/dist/workspace/search.js.map +1 -0
- package/dist/workspace/text.d.ts +8 -0
- package/dist/workspace/text.d.ts.map +1 -0
- package/dist/workspace/text.js +87 -0
- package/dist/workspace/text.js.map +1 -0
- package/dist/workspace/types.d.ts +103 -0
- package/dist/workspace/types.d.ts.map +1 -0
- package/dist/workspace/types.js +27 -0
- package/dist/workspace/types.js.map +1 -0
- package/dist/workspace/write.d.ts +4 -0
- package/dist/workspace/write.d.ts.map +1 -0
- package/dist/workspace/write.js +83 -0
- package/dist/workspace/write.js.map +1 -0
- package/dist/workspace.d.ts +16 -64
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +39 -486
- package/dist/workspace.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import createIgnore, {} from "ignore";
|
|
4
|
+
export const DEFAULT_IGNORE_PATTERNS = [
|
|
5
|
+
".git/",
|
|
6
|
+
"node_modules/",
|
|
7
|
+
"dist/",
|
|
8
|
+
"build/",
|
|
9
|
+
"coverage/",
|
|
10
|
+
".next/",
|
|
11
|
+
".cache/",
|
|
12
|
+
];
|
|
13
|
+
export function isDiscoveryIgnored(relativePath, isDirectory, matcher) {
|
|
14
|
+
if (relativePath === ".") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return matcher.ignores(isDirectory ? `${relativePath}/` : relativePath);
|
|
18
|
+
}
|
|
19
|
+
export async function createIgnoreMatcher(root, maxFileBytes) {
|
|
20
|
+
const matcher = createIgnore();
|
|
21
|
+
const ignorePath = path.join(root, ".gitignore");
|
|
22
|
+
try {
|
|
23
|
+
const stats = await lstat(ignorePath);
|
|
24
|
+
if (stats.isFile() &&
|
|
25
|
+
!stats.isSymbolicLink() &&
|
|
26
|
+
stats.size <= maxFileBytes) {
|
|
27
|
+
matcher.add(await readFile(ignorePath, "utf8"));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// A missing or unreadable root .gitignore does not prevent discovery.
|
|
32
|
+
}
|
|
33
|
+
return matcher.add(DEFAULT_IGNORE_PATTERNS);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/workspace/ignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,YAAY,EAAE,EAAe,MAAM,QAAQ,CAAC;AAInD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,eAAe;IACf,OAAO;IACP,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,SAAS;CACD,CAAC;AAEX,MAAM,UAAU,kBAAkB,CAChC,YAAoB,EACpB,WAAoB,EACpB,OAAe;IAEf,IAAI,YAAY,KAAK,GAAG,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,YAAoB;IAEpB,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,IACE,KAAK,CAAC,MAAM,EAAE;YACd,CAAC,KAAK,CAAC,cAAc,EAAE;YACvB,KAAK,CAAC,IAAI,IAAI,YAAY,EAC1B,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/workspace/list.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAEpB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAYpB,wBAAsB,SAAS,CAC7B,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAuF1B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { readdir, lstat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_LIST_DEPTH, DEFAULT_LIST_ENTRIES, MAX_LIST_DEPTH, MAX_LIST_ENTRIES, WorkspaceError, } from "./types.js";
|
|
4
|
+
import { compareCodePoints, isForbiddenRelativePath, joinWorkspacePath, rejectExplicitDirectorySymlink, resolveExistingPath, rootRelativeDirectory, } from "./paths.js";
|
|
5
|
+
import { createIgnoreMatcher, isDiscoveryIgnored } from "./ignore.js";
|
|
6
|
+
import { boundedPositiveInteger } from "./text.js";
|
|
7
|
+
export async function listFiles(limits, options = {}) {
|
|
8
|
+
const relativePath = options.path ?? ".";
|
|
9
|
+
const maxDepth = boundedPositiveInteger(options.maxDepth ?? DEFAULT_LIST_DEPTH, "maxDepth", MAX_LIST_DEPTH);
|
|
10
|
+
const maxEntries = boundedPositiveInteger(options.maxEntries ?? DEFAULT_LIST_ENTRIES, "maxEntries", MAX_LIST_ENTRIES);
|
|
11
|
+
const start = await resolveExistingPath(limits.root, relativePath);
|
|
12
|
+
const stats = await lstat(start.realTarget);
|
|
13
|
+
if (!stats.isDirectory()) {
|
|
14
|
+
throw new WorkspaceError("not_a_directory", `Path is not a directory: ${relativePath}`);
|
|
15
|
+
}
|
|
16
|
+
await rejectExplicitDirectorySymlink(limits.root, start, relativePath);
|
|
17
|
+
const matcher = await createIgnoreMatcher(limits.root, limits.maxFileBytes);
|
|
18
|
+
if (isDiscoveryIgnored(start.relativePath, true, matcher)) {
|
|
19
|
+
return { entries: [], truncated: false };
|
|
20
|
+
}
|
|
21
|
+
const entries = [];
|
|
22
|
+
let truncated = false;
|
|
23
|
+
const visit = async (absoluteDirectory, workspaceRelativeDirectory, depth) => {
|
|
24
|
+
let directoryEntries;
|
|
25
|
+
try {
|
|
26
|
+
directoryEntries = await readdir(absoluteDirectory, {
|
|
27
|
+
withFileTypes: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
directoryEntries.sort((left, right) => compareCodePoints(left.name, right.name));
|
|
34
|
+
for (const directoryEntry of directoryEntries) {
|
|
35
|
+
const entryPath = joinWorkspacePath(workspaceRelativeDirectory, directoryEntry.name);
|
|
36
|
+
const isDirectory = directoryEntry.isDirectory();
|
|
37
|
+
if (directoryEntry.isSymbolicLink() ||
|
|
38
|
+
(!isDirectory && !directoryEntry.isFile()) ||
|
|
39
|
+
isForbiddenRelativePath(entryPath) ||
|
|
40
|
+
isDiscoveryIgnored(entryPath, isDirectory, matcher)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (entries.length >= maxEntries) {
|
|
44
|
+
truncated = true;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
entries.push({
|
|
48
|
+
path: isDirectory ? `${entryPath}/` : entryPath,
|
|
49
|
+
type: isDirectory ? "directory" : "file",
|
|
50
|
+
});
|
|
51
|
+
if (isDirectory && depth < maxDepth) {
|
|
52
|
+
const shouldContinue = await visit(path.join(absoluteDirectory, directoryEntry.name), entryPath, depth + 1);
|
|
53
|
+
if (!shouldContinue) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
};
|
|
60
|
+
await visit(start.realTarget, rootRelativeDirectory(start.relativePath), 1);
|
|
61
|
+
return { entries, truncated };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/workspace/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,cAAc,GAKf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,8BAA8B,EAC9B,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAuB,EACvB,OAAO,GAAqB,EAAE;IAE9B,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC;IACzC,MAAM,QAAQ,GAAG,sBAAsB,CACrC,OAAO,CAAC,QAAQ,IAAI,kBAAkB,EACtC,UAAU,EACV,cAAc,CACf,CAAC;IACF,MAAM,UAAU,GAAG,sBAAsB,CACvC,OAAO,CAAC,UAAU,IAAI,oBAAoB,EAC1C,YAAY,EACZ,gBAAgB,CACjB,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,cAAc,CACtB,iBAAiB,EACjB,4BAA4B,YAAY,EAAE,CAC3C,CAAC;IACJ,CAAC;IACD,MAAM,8BAA8B,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IAEvE,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC5E,IAAI,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,KAAK,GAAG,KAAK,EACjB,iBAAyB,EACzB,0BAAkC,EAClC,KAAa,EACK,EAAE;QACpB,IAAI,gBAAgB,CAAC;QACrB,IAAI,CAAC;YACH,gBAAgB,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE;gBAClD,aAAa,EAAE,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACpC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CACzC,CAAC;QAEF,KAAK,MAAM,cAAc,IAAI,gBAAgB,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAG,iBAAiB,CACjC,0BAA0B,EAC1B,cAAc,CAAC,IAAI,CACpB,CAAC;YACF,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;YACjD,IACE,cAAc,CAAC,cAAc,EAAE;gBAC/B,CAAC,CAAC,WAAW,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;gBAC1C,uBAAuB,CAAC,SAAS,CAAC;gBAClC,kBAAkB,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,CAAC,EACnD,CAAC;gBACD,SAAS;YACX,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;gBACjC,SAAS,GAAG,IAAI,CAAC;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS;gBAC/C,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;aACzC,CAAC,CAAC;YAEH,IAAI,WAAW,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;gBACpC,MAAM,cAAc,GAAG,MAAM,KAAK,CAChC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,EACjD,SAAS,EACT,KAAK,GAAG,CAAC,CACV,CAAC;gBACF,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare const ALLOWED_ENV_FILES: Set<string>;
|
|
2
|
+
export declare const FORBIDDEN_DIRECTORY_NAMES: Set<string>;
|
|
3
|
+
export declare const FORBIDDEN_FILE_NAMES: Set<string>;
|
|
4
|
+
export declare const FORBIDDEN_FILE_EXTENSIONS: Set<string>;
|
|
5
|
+
export interface ResolvedPath {
|
|
6
|
+
readonly lexicalTarget: string;
|
|
7
|
+
readonly realRoot: string;
|
|
8
|
+
readonly realTarget: string;
|
|
9
|
+
readonly relativePath: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function isForbiddenRelativePath(relativePath: string): boolean;
|
|
12
|
+
export declare function rootRelativeDirectory(relativePath: string): string;
|
|
13
|
+
export declare function joinWorkspacePath(directory: string, name: string): string;
|
|
14
|
+
export declare function toWorkspacePath(relativePath: string): string;
|
|
15
|
+
export declare function compareCodePoints(left: string, right: string): number;
|
|
16
|
+
export declare function isPathInside(root: string, candidate: string): boolean;
|
|
17
|
+
export declare function normalizeRelativePath(root: string, relativePath: string): {
|
|
18
|
+
readonly lexicalTarget: string;
|
|
19
|
+
readonly relativePath: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function resolveExistingPath(root: string, relativePath: string): Promise<ResolvedPath>;
|
|
22
|
+
export declare function rejectExplicitDirectorySymlink(root: string, resolved: ResolvedPath, requestedPath: string): Promise<void>;
|
|
23
|
+
export interface ResolvedWritePath {
|
|
24
|
+
readonly lexicalTarget: string;
|
|
25
|
+
readonly realRoot: string;
|
|
26
|
+
readonly relativePath: string;
|
|
27
|
+
/** True when the target itself already exists as a regular file. */
|
|
28
|
+
readonly exists: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolves a path that may not exist yet.
|
|
32
|
+
*
|
|
33
|
+
* Reads can lean on `realpath` because the target is already there. A write
|
|
34
|
+
* target usually is not, so the boundary is proven against the deepest
|
|
35
|
+
* ancestor that does exist: every existing segment must be a real directory
|
|
36
|
+
* rather than a symlink, and that ancestor must resolve inside the workspace.
|
|
37
|
+
* A symlink planted anywhere along the way is therefore rejected before any
|
|
38
|
+
* bytes are written.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveWritePath(root: string, relativePath: string): Promise<ResolvedWritePath>;
|
|
41
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/workspace/paths.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,iBAAiB,aAI5B,CAAC;AACH,eAAO,MAAM,yBAAyB,aAAoC,CAAC;AAC3E,eAAO,MAAM,oBAAoB,aAK/B,CAAC;AACH,eAAO,MAAM,yBAAyB,aAA4C,CAAC;AAEnF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAyBrE;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAarE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAQrE;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CA+BnE;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAED,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,YAAY,EACtB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAyE5B"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { lstat, realpath } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { MAX_RELATIVE_PATH_CHARACTERS, WorkspaceError, } from "./types.js";
|
|
4
|
+
export const ALLOWED_ENV_FILES = new Set([
|
|
5
|
+
".env.example",
|
|
6
|
+
".env.sample",
|
|
7
|
+
".env.template",
|
|
8
|
+
]);
|
|
9
|
+
export const FORBIDDEN_DIRECTORY_NAMES = new Set([".git", ".ssh", ".aws"]);
|
|
10
|
+
export const FORBIDDEN_FILE_NAMES = new Set([
|
|
11
|
+
".npmrc",
|
|
12
|
+
".pypirc",
|
|
13
|
+
"id_rsa",
|
|
14
|
+
"id_ed25519",
|
|
15
|
+
]);
|
|
16
|
+
export const FORBIDDEN_FILE_EXTENSIONS = new Set([".pem", ".key", ".p12", ".pfx"]);
|
|
17
|
+
export function isForbiddenRelativePath(relativePath) {
|
|
18
|
+
if (relativePath === ".") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const segments = relativePath
|
|
22
|
+
.split("/")
|
|
23
|
+
.filter((segment) => segment.length > 0);
|
|
24
|
+
const lowerSegments = segments.map((segment) => segment.toLowerCase());
|
|
25
|
+
if (lowerSegments.some((segment) => FORBIDDEN_DIRECTORY_NAMES.has(segment))) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
const basename = lowerSegments.at(-1);
|
|
29
|
+
if (basename === undefined) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (basename === ".env" || basename.startsWith(".env.")) {
|
|
33
|
+
return !ALLOWED_ENV_FILES.has(basename);
|
|
34
|
+
}
|
|
35
|
+
return (FORBIDDEN_FILE_NAMES.has(basename) ||
|
|
36
|
+
FORBIDDEN_FILE_EXTENSIONS.has(path.posix.extname(basename)));
|
|
37
|
+
}
|
|
38
|
+
export function rootRelativeDirectory(relativePath) {
|
|
39
|
+
return relativePath === "." ? "" : relativePath;
|
|
40
|
+
}
|
|
41
|
+
export function joinWorkspacePath(directory, name) {
|
|
42
|
+
return directory.length === 0 ? name : `${directory}/${name}`;
|
|
43
|
+
}
|
|
44
|
+
export function toWorkspacePath(relativePath) {
|
|
45
|
+
return relativePath.length === 0
|
|
46
|
+
? "."
|
|
47
|
+
: relativePath.split(path.sep).join("/");
|
|
48
|
+
}
|
|
49
|
+
export function compareCodePoints(left, right) {
|
|
50
|
+
const leftPoints = [...left].map((character) => character.codePointAt(0) ?? 0);
|
|
51
|
+
const rightPoints = [...right].map((character) => character.codePointAt(0) ?? 0);
|
|
52
|
+
const sharedLength = Math.min(leftPoints.length, rightPoints.length);
|
|
53
|
+
for (let index = 0; index < sharedLength; index += 1) {
|
|
54
|
+
const difference = (leftPoints[index] ?? 0) - (rightPoints[index] ?? 0);
|
|
55
|
+
if (difference !== 0) {
|
|
56
|
+
return difference;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return leftPoints.length - rightPoints.length;
|
|
60
|
+
}
|
|
61
|
+
export function isPathInside(root, candidate) {
|
|
62
|
+
const relative = path.relative(root, candidate);
|
|
63
|
+
return (relative === "" ||
|
|
64
|
+
(!relative.startsWith(`..${path.sep}`) &&
|
|
65
|
+
relative !== ".." &&
|
|
66
|
+
!path.isAbsolute(relative)));
|
|
67
|
+
}
|
|
68
|
+
export function normalizeRelativePath(root, relativePath) {
|
|
69
|
+
if (typeof relativePath !== "string" ||
|
|
70
|
+
relativePath.length === 0 ||
|
|
71
|
+
relativePath.length > MAX_RELATIVE_PATH_CHARACTERS ||
|
|
72
|
+
relativePath.includes("\0") ||
|
|
73
|
+
path.isAbsolute(relativePath)) {
|
|
74
|
+
throw new WorkspaceError("invalid_path", "Workspace tools require a non-empty path relative to the workspace.");
|
|
75
|
+
}
|
|
76
|
+
const lexicalTarget = path.resolve(root, relativePath);
|
|
77
|
+
if (!isPathInside(root, lexicalTarget)) {
|
|
78
|
+
throw new WorkspaceError("outside_workspace", `Path escapes the workspace: ${relativePath}`);
|
|
79
|
+
}
|
|
80
|
+
const normalizedRelativePath = toWorkspacePath(path.relative(root, lexicalTarget));
|
|
81
|
+
if (isForbiddenRelativePath(normalizedRelativePath)) {
|
|
82
|
+
throw new WorkspaceError("forbidden_path", "Access to this sensitive workspace path is not allowed.");
|
|
83
|
+
}
|
|
84
|
+
return { lexicalTarget, relativePath: normalizedRelativePath };
|
|
85
|
+
}
|
|
86
|
+
export async function resolveExistingPath(root, relativePath) {
|
|
87
|
+
const normalized = normalizeRelativePath(root, relativePath);
|
|
88
|
+
let realRoot;
|
|
89
|
+
let realTarget;
|
|
90
|
+
try {
|
|
91
|
+
[realRoot, realTarget] = await Promise.all([
|
|
92
|
+
realpath(root),
|
|
93
|
+
realpath(normalized.lexicalTarget),
|
|
94
|
+
]);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
throw new WorkspaceError("not_found", `Path does not exist: ${relativePath}`, { cause: error });
|
|
98
|
+
}
|
|
99
|
+
if (!isPathInside(realRoot, realTarget)) {
|
|
100
|
+
throw new WorkspaceError("outside_workspace", `Path escapes the workspace: ${relativePath}`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
lexicalTarget: normalized.lexicalTarget,
|
|
104
|
+
realRoot,
|
|
105
|
+
realTarget,
|
|
106
|
+
relativePath: normalized.relativePath,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function rejectExplicitDirectorySymlink(root, resolved, requestedPath) {
|
|
110
|
+
if (resolved.relativePath === ".") {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
let currentPath = root;
|
|
114
|
+
for (const segment of resolved.relativePath.split("/")) {
|
|
115
|
+
currentPath = path.join(currentPath, segment);
|
|
116
|
+
let lexicalStats;
|
|
117
|
+
try {
|
|
118
|
+
lexicalStats = await lstat(currentPath);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw new WorkspaceError("not_found", `Path does not exist: ${requestedPath}`, { cause: error });
|
|
122
|
+
}
|
|
123
|
+
if (lexicalStats.isSymbolicLink()) {
|
|
124
|
+
throw new WorkspaceError("invalid_path", `Directory symlinks are not followed: ${requestedPath}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Resolves a path that may not exist yet.
|
|
130
|
+
*
|
|
131
|
+
* Reads can lean on `realpath` because the target is already there. A write
|
|
132
|
+
* target usually is not, so the boundary is proven against the deepest
|
|
133
|
+
* ancestor that does exist: every existing segment must be a real directory
|
|
134
|
+
* rather than a symlink, and that ancestor must resolve inside the workspace.
|
|
135
|
+
* A symlink planted anywhere along the way is therefore rejected before any
|
|
136
|
+
* bytes are written.
|
|
137
|
+
*/
|
|
138
|
+
export async function resolveWritePath(root, relativePath) {
|
|
139
|
+
const normalized = normalizeRelativePath(root, relativePath);
|
|
140
|
+
if (normalized.relativePath === ".") {
|
|
141
|
+
throw new WorkspaceError("invalid_path", "The workspace root is not a writable file path.");
|
|
142
|
+
}
|
|
143
|
+
let realRoot;
|
|
144
|
+
try {
|
|
145
|
+
realRoot = await realpath(root);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
throw new WorkspaceError("not_found", `Workspace root does not exist: ${root}`, { cause: error });
|
|
149
|
+
}
|
|
150
|
+
const segments = normalized.relativePath.split("/");
|
|
151
|
+
let currentPath = root;
|
|
152
|
+
let exists = false;
|
|
153
|
+
for (const [index, segment] of segments.entries()) {
|
|
154
|
+
currentPath = path.join(currentPath, segment);
|
|
155
|
+
const isFinalSegment = index === segments.length - 1;
|
|
156
|
+
let segmentStats;
|
|
157
|
+
try {
|
|
158
|
+
segmentStats = await lstat(currentPath);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// This segment does not exist yet. Nothing below it can exist either,
|
|
162
|
+
// so the remaining segments need no symlink check.
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
if (segmentStats.isSymbolicLink()) {
|
|
166
|
+
throw new WorkspaceError("invalid_path", `Symlinks are not followed: ${relativePath}`);
|
|
167
|
+
}
|
|
168
|
+
if (isFinalSegment) {
|
|
169
|
+
if (!segmentStats.isFile()) {
|
|
170
|
+
throw new WorkspaceError("not_a_file", `Path is not a regular file: ${relativePath}`);
|
|
171
|
+
}
|
|
172
|
+
exists = true;
|
|
173
|
+
}
|
|
174
|
+
else if (!segmentStats.isDirectory()) {
|
|
175
|
+
throw new WorkspaceError("not_a_directory", `Path is not a directory: ${segments.slice(0, index + 1).join("/")}`);
|
|
176
|
+
}
|
|
177
|
+
const realSegment = await realpath(currentPath);
|
|
178
|
+
if (!isPathInside(realRoot, realSegment)) {
|
|
179
|
+
throw new WorkspaceError("outside_workspace", `Path escapes the workspace: ${relativePath}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
lexicalTarget: normalized.lexicalTarget,
|
|
184
|
+
realRoot,
|
|
185
|
+
relativePath: normalized.relativePath,
|
|
186
|
+
exists,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/workspace/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ReadTextFileOptions, type TextFileSlice, type WorkspaceLimits } from "./types.js";
|
|
2
|
+
export declare function readFullTextFile(limits: WorkspaceLimits, relativePath: string): Promise<string>;
|
|
3
|
+
export declare function readTextFile(limits: WorkspaceLimits, relativePath: string, options?: ReadTextFileOptions): Promise<TextFileSlice>;
|
|
4
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/workspace/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAQpB,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAuCxB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DEFAULT_READ_LINE_COUNT, MAX_READ_LINE_COUNT, invalidRange, } from "./types.js";
|
|
2
|
+
import { resolveExistingPath } from "./paths.js";
|
|
3
|
+
import { boundedPositiveInteger, readUtf8File, splitLinesPreservingEndings, } from "./text.js";
|
|
4
|
+
export async function readFullTextFile(limits, relativePath) {
|
|
5
|
+
const resolved = await resolveExistingPath(limits.root, relativePath);
|
|
6
|
+
return readUtf8File(resolved.realTarget, relativePath, limits.maxFileBytes);
|
|
7
|
+
}
|
|
8
|
+
export async function readTextFile(limits, relativePath, options = {}) {
|
|
9
|
+
const startLine = boundedPositiveInteger(options.startLine ?? 1, "startLine", Number.MAX_SAFE_INTEGER);
|
|
10
|
+
const lineCount = boundedPositiveInteger(options.lineCount ?? DEFAULT_READ_LINE_COUNT, "lineCount", MAX_READ_LINE_COUNT);
|
|
11
|
+
const contents = await readFullTextFile(limits, relativePath);
|
|
12
|
+
const lines = splitLinesPreservingEndings(contents);
|
|
13
|
+
if (lines.length === 0) {
|
|
14
|
+
if (startLine !== 1) {
|
|
15
|
+
throw invalidRange(relativePath, startLine, 0);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
content: "",
|
|
19
|
+
startLine: 1,
|
|
20
|
+
endLine: 0,
|
|
21
|
+
totalLines: 0,
|
|
22
|
+
truncated: false,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (startLine > lines.length) {
|
|
26
|
+
throw invalidRange(relativePath, startLine, lines.length);
|
|
27
|
+
}
|
|
28
|
+
const endLine = Math.min(lines.length, startLine + lineCount - 1);
|
|
29
|
+
return {
|
|
30
|
+
content: lines.slice(startLine - 1, endLine).join(""),
|
|
31
|
+
startLine,
|
|
32
|
+
endLine,
|
|
33
|
+
totalLines: lines.length,
|
|
34
|
+
truncated: endLine < lines.length,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/workspace/read.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,GAIb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,WAAW,CAAC;AAEnB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAuB,EACvB,YAAoB;IAEpB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtE,OAAO,YAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,YAAoB,EACpB,OAAO,GAAwB,EAAE;IAEjC,MAAM,SAAS,GAAG,sBAAsB,CACtC,OAAO,CAAC,SAAS,IAAI,CAAC,EACtB,WAAW,EACX,MAAM,CAAC,gBAAgB,CACxB,CAAC;IACF,MAAM,SAAS,GAAG,sBAAsB,CACtC,OAAO,CAAC,SAAS,IAAI,uBAAuB,EAC5C,WAAW,EACX,mBAAmB,CACpB,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAEpD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM,YAAY,CAAC,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,OAAO;YACL,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,YAAY,CAAC,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC;IAClE,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,SAAS;QACT,OAAO;QACP,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,SAAS,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/workspace/search.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAyCpB,wBAAsB,UAAU,CAC9B,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAuJ3B"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { readdir, lstat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_SEARCH_RESULTS, MAX_SEARCH_RESULTS, WorkspaceError, } from "./types.js";
|
|
4
|
+
import { compareCodePoints, isForbiddenRelativePath, joinWorkspacePath, rejectExplicitDirectorySymlink, resolveExistingPath, rootRelativeDirectory, } from "./paths.js";
|
|
5
|
+
import { createIgnoreMatcher, isDiscoveryIgnored } from "./ignore.js";
|
|
6
|
+
import { boundedPositiveInteger, createMatchPreview, readUtf8File, splitLines, validateSearchQuery, } from "./text.js";
|
|
7
|
+
function emptySearchResult() {
|
|
8
|
+
return { matches: [], truncated: false, scannedFiles: 0, skippedFiles: 0 };
|
|
9
|
+
}
|
|
10
|
+
function searchResult(state) {
|
|
11
|
+
return {
|
|
12
|
+
matches: state.matches,
|
|
13
|
+
truncated: state.truncated,
|
|
14
|
+
scannedFiles: state.scannedFiles,
|
|
15
|
+
skippedFiles: state.skippedFiles,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export async function searchText(limits, options) {
|
|
19
|
+
validateSearchQuery(options.query);
|
|
20
|
+
const relativePath = options.path ?? ".";
|
|
21
|
+
const maxResults = boundedPositiveInteger(options.maxResults ?? DEFAULT_SEARCH_RESULTS, "maxResults", MAX_SEARCH_RESULTS);
|
|
22
|
+
const start = await resolveExistingPath(limits.root, relativePath);
|
|
23
|
+
const stats = await lstat(start.realTarget);
|
|
24
|
+
const matcher = await createIgnoreMatcher(limits.root, limits.maxFileBytes);
|
|
25
|
+
const startIsDirectory = stats.isDirectory();
|
|
26
|
+
if (!startIsDirectory && !stats.isFile()) {
|
|
27
|
+
throw new WorkspaceError("not_a_file", `Path is not a regular file or directory: ${relativePath}`);
|
|
28
|
+
}
|
|
29
|
+
if (startIsDirectory) {
|
|
30
|
+
await rejectExplicitDirectorySymlink(limits.root, start, relativePath);
|
|
31
|
+
}
|
|
32
|
+
if (isDiscoveryIgnored(start.relativePath, startIsDirectory, matcher)) {
|
|
33
|
+
return emptySearchResult();
|
|
34
|
+
}
|
|
35
|
+
const state = {
|
|
36
|
+
matches: [],
|
|
37
|
+
scannedFiles: 0,
|
|
38
|
+
skippedFiles: 0,
|
|
39
|
+
examinedFiles: 0,
|
|
40
|
+
scannedBytes: 0,
|
|
41
|
+
truncated: false,
|
|
42
|
+
};
|
|
43
|
+
const scanFile = async (absoluteFile, workspaceRelativeFile) => {
|
|
44
|
+
if (state.examinedFiles >= limits.maxSearchFiles) {
|
|
45
|
+
state.truncated = true;
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
state.examinedFiles += 1;
|
|
49
|
+
let resolved;
|
|
50
|
+
let fileStats;
|
|
51
|
+
try {
|
|
52
|
+
resolved = await resolveExistingPath(limits.root, workspaceRelativeFile);
|
|
53
|
+
fileStats = await lstat(resolved.realTarget);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
state.skippedFiles += 1;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (!fileStats.isFile() || fileStats.size > limits.maxFileBytes) {
|
|
60
|
+
state.skippedFiles += 1;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
if (state.scannedBytes + fileStats.size > limits.maxSearchBytes) {
|
|
64
|
+
state.truncated = true;
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
let contents;
|
|
68
|
+
try {
|
|
69
|
+
contents = await readUtf8File(absoluteFile === resolved.realTarget
|
|
70
|
+
? absoluteFile
|
|
71
|
+
: resolved.realTarget, workspaceRelativeFile, limits.maxFileBytes);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
state.skippedFiles += 1;
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
state.scannedBytes += Buffer.byteLength(contents, "utf8");
|
|
78
|
+
state.scannedFiles += 1;
|
|
79
|
+
const lines = splitLines(contents);
|
|
80
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
81
|
+
const line = lines[index];
|
|
82
|
+
if (line === undefined || !line.includes(options.query)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (state.matches.length >= maxResults) {
|
|
86
|
+
state.truncated = true;
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
state.matches.push({
|
|
90
|
+
path: workspaceRelativeFile,
|
|
91
|
+
line: index + 1,
|
|
92
|
+
preview: createMatchPreview(line, options.query),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
};
|
|
97
|
+
if (stats.isFile()) {
|
|
98
|
+
await scanFile(start.realTarget, start.relativePath);
|
|
99
|
+
return searchResult(state);
|
|
100
|
+
}
|
|
101
|
+
const visit = async (absoluteDirectory, workspaceRelativeDirectory) => {
|
|
102
|
+
let directoryEntries;
|
|
103
|
+
try {
|
|
104
|
+
directoryEntries = await readdir(absoluteDirectory, {
|
|
105
|
+
withFileTypes: true,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
directoryEntries.sort((left, right) => compareCodePoints(left.name, right.name));
|
|
112
|
+
for (const directoryEntry of directoryEntries) {
|
|
113
|
+
const entryPath = joinWorkspacePath(workspaceRelativeDirectory, directoryEntry.name);
|
|
114
|
+
const isDirectory = directoryEntry.isDirectory();
|
|
115
|
+
if (directoryEntry.isSymbolicLink() ||
|
|
116
|
+
(!isDirectory && !directoryEntry.isFile()) ||
|
|
117
|
+
isForbiddenRelativePath(entryPath) ||
|
|
118
|
+
isDiscoveryIgnored(entryPath, isDirectory, matcher)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const absoluteEntry = path.join(absoluteDirectory, directoryEntry.name);
|
|
122
|
+
const shouldContinue = isDirectory
|
|
123
|
+
? await visit(absoluteEntry, entryPath)
|
|
124
|
+
: await scanFile(absoluteEntry, entryPath);
|
|
125
|
+
if (!shouldContinue) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
await visit(start.realTarget, rootRelativeDirectory(start.relativePath));
|
|
132
|
+
return searchResult(state);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/workspace/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function readUtf8File(absolutePath: string, displayPath: string, maxFileBytes: number): Promise<string>;
|
|
2
|
+
export declare function validateSearchQuery(query: string): void;
|
|
3
|
+
export declare function positiveSafeInteger(value: number, name: string): number;
|
|
4
|
+
export declare function boundedPositiveInteger(value: number, name: string, maximum: number): number;
|
|
5
|
+
export declare function splitLinesPreservingEndings(contents: string): string[];
|
|
6
|
+
export declare function splitLines(contents: string): string[];
|
|
7
|
+
export declare function createMatchPreview(line: string, query: string): string;
|
|
8
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/workspace/text.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAavD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,MAAM,CAMR;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAStE;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAIrD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAqCtE"}
|