@young1lin/dsh-ui-gitworkbench 0.1.14 → 0.1.16
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 +23 -0
- package/CHANGELOG_EN.md +23 -0
- package/README.md +29 -3
- package/README_EN.md +1 -1
- package/lib/client.js +1512 -470
- package/lib/dir-listing.js +34 -0
- package/lib/fs-remove.js +5 -36
- package/lib/index.js +346 -117
- package/lib/path-lock.js +54 -0
- package/lib/repo-root.js +60 -0
- package/lib/worktree.js +83 -0
- package/lib/write-checked.js +1 -1
- package/package.json +5 -5
- package/src/client/ChromeGlyph.tsx +5 -0
- package/src/client/CodeEditor.tsx +19 -1
- package/src/client/DiffViews.tsx +116 -121
- package/src/client/FileBrowser.tsx +196 -23
- package/src/client/GitWorkbenchPanel.module.css +1 -0
- package/src/client/GitWorkbenchPanel.tsx +100 -12
- package/src/client/SideRails.tsx +106 -0
- package/src/client/diff-cells.tsx +147 -0
- package/src/client/diff-nav.ts +4 -1
- package/src/client/dir-tree.ts +31 -1
- package/src/client/file-rows.ts +40 -0
- package/src/client/h-rail.ts +70 -0
- package/src/client/ignored-cache.ts +193 -0
- package/src/client/index.ts +22 -3
- package/src/client/locales.ts +12 -2
- package/src/client/row-heights.ts +225 -0
- package/src/client/styles/changes.css +33 -2
- package/src/client/styles/controls.css +5 -0
- package/src/client/styles/files.css +5 -0
- package/src/client/styles/rails.css +72 -0
- package/src/client/use-row-window.ts +7 -3
- package/src/client/use-variable-row-window.ts +210 -0
- package/src/dir-listing.ts +47 -0
- package/src/fs-remove.ts +5 -36
- package/src/index.ts +372 -118
- package/src/path-lock.ts +56 -0
- package/src/repo-root.ts +66 -0
- package/src/types/dsh-shim.d.ts +12 -2
- package/src/worktree.ts +97 -0
- package/src/write-checked.ts +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One lazily listed directory, shaped for the wire.
|
|
3
|
+
*
|
|
4
|
+
* The Files tab browses ignored directories by reading them from the
|
|
5
|
+
* filesystem ONE level at a time — git cannot do this scoped: a pathspec
|
|
6
|
+
* under `--directory` still collapses the whole ignored directory to a
|
|
7
|
+
* single line, and dropping `--directory` would enumerate every file inside
|
|
8
|
+
* `node_modules` at once. A `readdir` is one level by construction, costs
|
|
9
|
+
* milliseconds, and says what a browser wants to know: what is HERE.
|
|
10
|
+
*
|
|
11
|
+
* Only the shaping is pure (ordering, capping); the read itself stays in
|
|
12
|
+
* `index.ts`, which vitest cannot load. Same split as `fs-remove.ts`.
|
|
13
|
+
*
|
|
14
|
+
* @module @young1lin/dsh-ui-gitworkbench/dir-listing
|
|
15
|
+
*/
|
|
16
|
+
/** The most entries one expansion returns. A real directory level is a few
|
|
17
|
+
* hundred at most (`node_modules`'s own top level); a cap beyond that is a
|
|
18
|
+
* reported fuse against a pathological directory, not a working number. */
|
|
19
|
+
export const DIR_CHILD_CAP = 5_000;
|
|
20
|
+
/**
|
|
21
|
+
* Order and cap raw readdir results: directories before files (the shape
|
|
22
|
+
* every file tree has, matching `treeRows`), each run by name, and a cut
|
|
23
|
+
* REPORTED rather than silent.
|
|
24
|
+
*
|
|
25
|
+
* @param raw - the directory's entries with their best-known dir-ness
|
|
26
|
+
* (symlinks already resolved by the caller).
|
|
27
|
+
* @param cap - most entries to return.
|
|
28
|
+
*/
|
|
29
|
+
export function shapeDirChildren(raw, cap = DIR_CHILD_CAP) {
|
|
30
|
+
const byName = (a, b) => a.name.localeCompare(b.name);
|
|
31
|
+
const ordered = [...raw.filter(entry => entry.dir).sort(byName), ...raw.filter(entry => !entry.dir).sort(byName)];
|
|
32
|
+
const truncated = ordered.length > cap;
|
|
33
|
+
return { entries: truncated ? ordered.slice(0, cap) : ordered, truncated };
|
|
34
|
+
}
|
package/lib/fs-remove.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* `git clean` refuses paths it cannot index, which on Windows includes every
|
|
7
7
|
* reserved device name (`nul`, `con`, `aux`, `com1`, and the same names with
|
|
8
8
|
* any extension). So the removal goes through the filesystem, where git's own
|
|
9
|
-
* refusal to leave the repository does not apply — hence the
|
|
10
|
-
* rather than a bare `rm`.
|
|
9
|
+
* refusal to leave the repository does not apply — hence the path lock in
|
|
10
|
+
* `path-lock.ts` rather than a bare `rm`.
|
|
11
11
|
*
|
|
12
12
|
* Lives outside `index.ts` so vitest can load it: the class there needs the
|
|
13
13
|
* dsh runtime, and the property worth testing is "what does this delete, and
|
|
@@ -16,36 +16,7 @@
|
|
|
16
16
|
* @module @young1lin/dsh-ui-gitworkbench/fs-remove
|
|
17
17
|
*/
|
|
18
18
|
import { rm } from 'node:fs/promises';
|
|
19
|
-
import {
|
|
20
|
-
import { isSafeRelativePath } from './discard-ops.js';
|
|
21
|
-
/**
|
|
22
|
-
* Resolve a repo-relative path against the worktree root, refusing to leave it.
|
|
23
|
-
*
|
|
24
|
-
* The second lock rather than the only one: {@link isSafeRelativePath} already
|
|
25
|
-
* rejected traversal spellings when the plan was made. This re-checks the
|
|
26
|
-
* RESOLVED path, which is the form the filesystem acts on, so a path that
|
|
27
|
-
* survives the first check by being spelled unusually still has to land inside
|
|
28
|
-
* the root to be acted on.
|
|
29
|
-
*
|
|
30
|
-
* @param root - the worktree directory, absolute.
|
|
31
|
-
* @param relative - repo-relative path from a plan step.
|
|
32
|
-
* @returns the absolute path to act on.
|
|
33
|
-
* @throws if the path is not a safe relative path, resolves outside the root,
|
|
34
|
-
* or IS the root.
|
|
35
|
-
*/
|
|
36
|
-
export function resolveInside(root, relative) {
|
|
37
|
-
if (!isSafeRelativePath(relative)) {
|
|
38
|
-
throw new Error(`unsafe path to delete: ${JSON.stringify(relative)}`);
|
|
39
|
-
}
|
|
40
|
-
const base = resolve(root);
|
|
41
|
-
const target = resolve(base, relative);
|
|
42
|
-
if (target === base)
|
|
43
|
-
throw new Error('refusing to delete the worktree root');
|
|
44
|
-
if (!target.startsWith(base + sep)) {
|
|
45
|
-
throw new Error(`refusing to delete outside the worktree: ${JSON.stringify(relative)}`);
|
|
46
|
-
}
|
|
47
|
-
return target;
|
|
48
|
-
}
|
|
19
|
+
import { resolveInside } from './path-lock.js';
|
|
49
20
|
/**
|
|
50
21
|
* Remove one entry from the worktree, having proven it is inside it.
|
|
51
22
|
*
|
|
@@ -60,10 +31,8 @@ export function resolveInside(root, relative) {
|
|
|
60
31
|
* `force` makes an absent entry a success: the reader asked for it to be gone,
|
|
61
32
|
* and it is.
|
|
62
33
|
*
|
|
63
|
-
* A symlinked directory inside the worktree could still point outward
|
|
64
|
-
*
|
|
65
|
-
* per segment on every delete would cost a stat per segment for a case git
|
|
66
|
-
* itself does not defend against.
|
|
34
|
+
* A symlinked directory inside the worktree could still point outward — the
|
|
35
|
+
* limit of a lexical resolve, stated where the lock is.
|
|
67
36
|
*
|
|
68
37
|
* @param root - the worktree directory, absolute.
|
|
69
38
|
* @param relative - repo-relative path from a plan step.
|