svn-agent-mcp 1.0.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/.editorconfig +12 -0
- package/.gitattributes +7 -0
- package/.github/workflows/ci.yml +39 -0
- package/.svn-mcp-policy.json +9 -0
- package/CHANGELOG.md +248 -0
- package/CONTRIBUTING.md +49 -0
- package/LICENSE +201 -0
- package/README.md +143 -0
- package/SECURITY.md +21 -0
- package/THIRD_PARTY_CHECKSUMS.txt +52 -0
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/bin/SlikSvn-DB44-20-x64.dll +0 -0
- package/bin/SlikSvn-libapr-1.dll +0 -0
- package/bin/SlikSvn-libaprutil-1.dll +0 -0
- package/bin/SlikSvn-libcrypto-3-x64.dll +0 -0
- package/bin/SlikSvn-libintl.dll +0 -0
- package/bin/SlikSvn-libsasl21.dll +0 -0
- package/bin/SlikSvn-libssl-3-x64.dll +0 -0
- package/bin/SlikSvn-libsvn_client-1.dll +0 -0
- package/bin/SlikSvn-libsvn_delta-1.dll +0 -0
- package/bin/SlikSvn-libsvn_diff-1.dll +0 -0
- package/bin/SlikSvn-libsvn_fs-1.dll +0 -0
- package/bin/SlikSvn-libsvn_fs_base-1.dll +0 -0
- package/bin/SlikSvn-libsvn_fs_fs-1.dll +0 -0
- package/bin/SlikSvn-libsvn_fs_util-1.dll +0 -0
- package/bin/SlikSvn-libsvn_fs_x-1.dll +0 -0
- package/bin/SlikSvn-libsvn_ra-1.dll +0 -0
- package/bin/SlikSvn-libsvn_repos-1.dll +0 -0
- package/bin/SlikSvn-libsvn_subr-1.dll +0 -0
- package/bin/SlikSvn-libsvn_wc-1.dll +0 -0
- package/bin/System64/concrt140.dll +0 -0
- package/bin/System64/msvcp140.dll +0 -0
- package/bin/System64/msvcp140_1.dll +0 -0
- package/bin/System64/msvcp140_2.dll +0 -0
- package/bin/System64/msvcp140_atomic_wait.dll +0 -0
- package/bin/System64/msvcp140_codecvt_ids.dll +0 -0
- package/bin/System64/vccorlib140.dll +0 -0
- package/bin/System64/vcruntime140.dll +0 -0
- package/bin/System64/vcruntime140_1.dll +0 -0
- package/bin/dos2unix.exe +0 -0
- package/bin/engines/capi.dll +0 -0
- package/bin/libsvnjavahl-1.dll +0 -0
- package/bin/mac2unix.exe +0 -0
- package/bin/svn-populate-node-origins-index.exe +0 -0
- package/bin/svn.exe +0 -0
- package/bin/svnadmin.exe +0 -0
- package/bin/svnauthz-validate.exe +0 -0
- package/bin/svnauthz.exe +0 -0
- package/bin/svnbench.exe +0 -0
- package/bin/svndumpfilter.exe +0 -0
- package/bin/svnfsfs.exe +0 -0
- package/bin/svnlook.exe +0 -0
- package/bin/svnmucc.exe +0 -0
- package/bin/svnrdump.exe +0 -0
- package/bin/svnserve.exe +0 -0
- package/bin/svnsync.exe +0 -0
- package/bin/svnversion.exe +0 -0
- package/bin/unix2dos.exe +0 -0
- package/bin/unix2mac.exe +0 -0
- package/dist/envelope.d.ts +39 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +137 -0
- package/dist/envelope.js.map +1 -0
- package/dist/eol.d.ts +15 -0
- package/dist/eol.d.ts.map +1 -0
- package/dist/eol.js +119 -0
- package/dist/eol.js.map +1 -0
- package/dist/guards.d.ts +26 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +306 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +221 -0
- package/dist/index.js.map +1 -0
- package/dist/parse/commitText.d.ts +2 -0
- package/dist/parse/commitText.d.ts.map +1 -0
- package/dist/parse/commitText.js +9 -0
- package/dist/parse/commitText.js.map +1 -0
- package/dist/parse/diffText.d.ts +7 -0
- package/dist/parse/diffText.d.ts.map +1 -0
- package/dist/parse/diffText.js +55 -0
- package/dist/parse/diffText.js.map +1 -0
- package/dist/parse/infoXml.d.ts +3 -0
- package/dist/parse/infoXml.d.ts.map +1 -0
- package/dist/parse/infoXml.js +35 -0
- package/dist/parse/infoXml.js.map +1 -0
- package/dist/parse/logXml.d.ts +10 -0
- package/dist/parse/logXml.d.ts.map +1 -0
- package/dist/parse/logXml.js +39 -0
- package/dist/parse/logXml.js.map +1 -0
- package/dist/parse/statusXml.d.ts +6 -0
- package/dist/parse/statusXml.d.ts.map +1 -0
- package/dist/parse/statusXml.js +64 -0
- package/dist/parse/statusXml.js.map +1 -0
- package/dist/parse/updateText.d.ts +6 -0
- package/dist/parse/updateText.d.ts.map +1 -0
- package/dist/parse/updateText.js +67 -0
- package/dist/parse/updateText.js.map +1 -0
- package/dist/runner.d.ts +41 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +270 -0
- package/dist/runner.js.map +1 -0
- package/dist/tools/composite.d.ts +15 -0
- package/dist/tools/composite.d.ts.map +1 -0
- package/dist/tools/composite.js +238 -0
- package/dist/tools/composite.js.map +1 -0
- package/dist/tools/diagnose.d.ts +6 -0
- package/dist/tools/diagnose.d.ts.map +1 -0
- package/dist/tools/diagnose.js +131 -0
- package/dist/tools/diagnose.js.map +1 -0
- package/dist/tools/mutating.d.ts +80 -0
- package/dist/tools/mutating.d.ts.map +1 -0
- package/dist/tools/mutating.js +558 -0
- package/dist/tools/mutating.js.map +1 -0
- package/dist/tools/readonly.d.ts +52 -0
- package/dist/tools/readonly.d.ts.map +1 -0
- package/dist/tools/readonly.js +638 -0
- package/dist/tools/readonly.js.map +1 -0
- package/dist/tools/selfcheck.d.ts +5 -0
- package/dist/tools/selfcheck.d.ts.map +1 -0
- package/dist/tools/selfcheck.js +91 -0
- package/dist/tools/selfcheck.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/README.md +11 -0
- package/docs/SPEC.md +964 -0
- package/docs/decisions/ADR-001-use-spec-v1-architecture.md +25 -0
- package/docs/decisions/ADR-002-use-capability-based-generic-svn-policy.md +31 -0
- package/docs/decisions/ADR-003-use-plug-and-play-global-registration.md +39 -0
- package/docs/decisions/ADR-004-borrow-diagnostics-not-external-mcp-surface.md +39 -0
- package/docs/svnrules.md +84 -0
- package/docs/toolrules.md +34 -0
- package/jest.config.cjs +14 -0
- package/package.json +51 -0
- package/scripts/clean.mjs +27 -0
- package/scripts/prepare-release.mjs +84 -0
- package/src/envelope.ts +182 -0
- package/src/eol.ts +137 -0
- package/src/guards.ts +362 -0
- package/src/index.ts +364 -0
- package/src/parse/commitText.ts +9 -0
- package/src/parse/diffText.ts +66 -0
- package/src/parse/infoXml.ts +51 -0
- package/src/parse/logXml.ts +64 -0
- package/src/parse/statusXml.ts +87 -0
- package/src/parse/updateText.ts +76 -0
- package/src/runner.ts +344 -0
- package/src/tools/composite.ts +289 -0
- package/src/tools/diagnose.ts +150 -0
- package/src/tools/mutating.ts +694 -0
- package/src/tools/readonly.ts +786 -0
- package/src/tools/selfcheck.ts +97 -0
- package/src/types.ts +76 -0
- package/tests/README.md +9 -0
- package/tests/diff-redaction.test.ts +146 -0
- package/tests/entrypoint.test.ts +49 -0
- package/tests/guards-eol.test.ts +170 -0
- package/tests/integration-svn.test.ts +709 -0
- package/tests/parsers.test.ts +119 -0
- package/tests/runner.test.ts +159 -0
- package/tests/selfcheck.test.ts +22 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import { parseCommittedRevision } from "../src/parse/commitText.js";
|
|
3
|
+
import { parseDiffText } from "../src/parse/diffText.js";
|
|
4
|
+
import { parseInfoXml } from "../src/parse/infoXml.js";
|
|
5
|
+
import { parseLogXml } from "../src/parse/logXml.js";
|
|
6
|
+
import { parseStatusXml } from "../src/parse/statusXml.js";
|
|
7
|
+
import { parseUpdateText } from "../src/parse/updateText.js";
|
|
8
|
+
|
|
9
|
+
describe("SVN text and XML parsers", () => {
|
|
10
|
+
it("counts per-file diff additions and removals without counting headers", () => {
|
|
11
|
+
const diff = parseDiffText(
|
|
12
|
+
[
|
|
13
|
+
"Index: src/example.ts",
|
|
14
|
+
"===================================================================",
|
|
15
|
+
"--- src/example.ts\t(revision 1)",
|
|
16
|
+
"+++ src/example.ts\t(working copy)",
|
|
17
|
+
"@@ -1,2 +1,3 @@",
|
|
18
|
+
" keep",
|
|
19
|
+
"-old",
|
|
20
|
+
"+new",
|
|
21
|
+
"+extra"
|
|
22
|
+
].join("\n"),
|
|
23
|
+
4
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
expect(diff.per_file).toEqual([{ path: "src/example.ts", added: 2, removed: 1, binary: false }]);
|
|
27
|
+
expect(diff.truncated).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("parses status XML into changed paths and conflicts", () => {
|
|
31
|
+
const parsed = parseStatusXml(`<?xml version="1.0"?>
|
|
32
|
+
<status>
|
|
33
|
+
<target path=".">
|
|
34
|
+
<entry path="src/a.ts"><wc-status item="modified" revision="1" /></entry>
|
|
35
|
+
<entry path="src/b.ts"><wc-status item="conflicted" revision="1" tree-conflicted="true" /></entry>
|
|
36
|
+
<entry path="src/props.txt"><wc-status item="normal" props="modified" /></entry>
|
|
37
|
+
<entry path="src/prop-conflict.txt"><wc-status item="normal" props="conflicted" /></entry>
|
|
38
|
+
</target>
|
|
39
|
+
</status>`);
|
|
40
|
+
|
|
41
|
+
expect(parsed.changed_paths).toEqual([
|
|
42
|
+
{ status: "M", path: "src/a.ts" },
|
|
43
|
+
{ status: "C", path: "src/b.ts" },
|
|
44
|
+
{ status: "_M", path: "src/props.txt" },
|
|
45
|
+
{ status: "C", path: "src/prop-conflict.txt" }
|
|
46
|
+
]);
|
|
47
|
+
expect(parsed.conflicts).toEqual([
|
|
48
|
+
{ path: "src/b.ts", type: "text" },
|
|
49
|
+
{ path: "src/b.ts", type: "tree" },
|
|
50
|
+
{ path: "src/prop-conflict.txt", type: "prop" }
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("parses svn info XML", () => {
|
|
55
|
+
const parsed = parseInfoXml(`<?xml version="1.0"?>
|
|
56
|
+
<info>
|
|
57
|
+
<entry kind="dir" path="." revision="7">
|
|
58
|
+
<url>file:///repo/trunk</url>
|
|
59
|
+
<repository><root>file:///repo</root></repository>
|
|
60
|
+
<wc-info><wcroot-abspath>C:\\work\\repo</wcroot-abspath></wc-info>
|
|
61
|
+
</entry>
|
|
62
|
+
</info>`);
|
|
63
|
+
|
|
64
|
+
expect(parsed[0]).toEqual({
|
|
65
|
+
url: "file:///repo/trunk",
|
|
66
|
+
repo_root: "file:///repo",
|
|
67
|
+
wc_root: "C:\\work\\repo",
|
|
68
|
+
revision: 7
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("uses null for info XML entries without a working-copy root", () => {
|
|
73
|
+
const parsed = parseInfoXml(`<?xml version="1.0"?>
|
|
74
|
+
<info>
|
|
75
|
+
<entry kind="dir" path="." revision="7">
|
|
76
|
+
<url>file:///repo/trunk</url>
|
|
77
|
+
<repository><root>file:///repo</root></repository>
|
|
78
|
+
</entry>
|
|
79
|
+
</info>`);
|
|
80
|
+
|
|
81
|
+
expect(parsed[0]?.wc_root).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("ignores svn update informational lines instead of parsing phantom paths", () => {
|
|
85
|
+
const parsed = parseUpdateText(
|
|
86
|
+
[
|
|
87
|
+
"Updating '.':",
|
|
88
|
+
"U src/a.ts",
|
|
89
|
+
"Restored 'src/gone.ts'",
|
|
90
|
+
"External at revision 41.",
|
|
91
|
+
"At revision 42.",
|
|
92
|
+
"Updated to revision 42."
|
|
93
|
+
].join("\n")
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(parsed.changed_paths).toEqual([{ status: "U", path: "src/a.ts" }]);
|
|
97
|
+
expect(parsed.conflicts).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("parses log XML and commit/update text", () => {
|
|
101
|
+
expect(parseCommittedRevision("Committed revision 42.")).toBe(42);
|
|
102
|
+
expect(parseUpdateText("U src/a.ts\nC src/b.ts\n C src/tree.ts\nSummary of conflicts:\n Tree conflicts: 2\n").conflicts).toEqual([
|
|
103
|
+
{ path: "src/b.ts", type: "text" },
|
|
104
|
+
{ path: "src/tree.ts", type: "tree" },
|
|
105
|
+
{ path: "", type: "tree" }
|
|
106
|
+
]);
|
|
107
|
+
expect(
|
|
108
|
+
parseLogXml(`<log><logentry revision="9"><author>a</author><date>d</date><msg>m</msg><paths><path action="M">/trunk/a</path></paths></logentry></log>`)
|
|
109
|
+
).toEqual([
|
|
110
|
+
{
|
|
111
|
+
rev: 9,
|
|
112
|
+
author: "a",
|
|
113
|
+
date: "d",
|
|
114
|
+
msg: "m",
|
|
115
|
+
changed_paths: [{ status: "M", path: "/trunk/a" }]
|
|
116
|
+
}
|
|
117
|
+
]);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import {
|
|
6
|
+
dos2UnixExecutable,
|
|
7
|
+
runExecutable,
|
|
8
|
+
runExecutableStreamingLines,
|
|
9
|
+
runSvn,
|
|
10
|
+
svnAdminExecutable,
|
|
11
|
+
svnExecutable,
|
|
12
|
+
svnVersionExecutable
|
|
13
|
+
} from "../src/runner.js";
|
|
14
|
+
|
|
15
|
+
describe("runner executable resolution", () => {
|
|
16
|
+
it("prefers bundled binaries when no explicit environment override is set", () => {
|
|
17
|
+
withCleanToolEnv(() => {
|
|
18
|
+
const bin = path.join(process.cwd(), "bin");
|
|
19
|
+
|
|
20
|
+
expect(path.normalize(svnExecutable())).toBe(path.join(bin, "svn.exe"));
|
|
21
|
+
expect(path.normalize(svnVersionExecutable())).toBe(path.join(bin, "svnversion.exe"));
|
|
22
|
+
expect(path.normalize(svnAdminExecutable())).toBe(path.join(bin, "svnadmin.exe"));
|
|
23
|
+
expect(path.normalize(dos2UnixExecutable("dos2unix"))).toBe(path.join(bin, "dos2unix.exe"));
|
|
24
|
+
expect(path.normalize(dos2UnixExecutable("unix2dos"))).toBe(path.join(bin, "unix2dos.exe"));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("keeps explicit environment overrides ahead of the bundled bin", () => {
|
|
29
|
+
withCleanToolEnv(() => {
|
|
30
|
+
const svn = path.join("C:", "custom", "svn.exe");
|
|
31
|
+
const eol = path.join("C:", "custom-eol");
|
|
32
|
+
|
|
33
|
+
process.env.SVN_AGENT_SVN_PATH = svn;
|
|
34
|
+
process.env.SVN_AGENT_DOS2UNIX_DIR = eol;
|
|
35
|
+
|
|
36
|
+
expect(path.normalize(svnExecutable())).toBe(svn);
|
|
37
|
+
expect(path.normalize(svnVersionExecutable())).toBe(path.join(path.dirname(svn), "svnversion.exe"));
|
|
38
|
+
expect(path.normalize(svnAdminExecutable())).toBe(path.join(path.dirname(svn), "svnadmin.exe"));
|
|
39
|
+
expect(path.normalize(dos2UnixExecutable("dos2unix"))).toBe(path.join(eol, "dos2unix.exe"));
|
|
40
|
+
expect(path.normalize(dos2UnixExecutable("unix2dos"))).toBe(path.join(eol, "unix2dos.exe"));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("supports a portable bundled-bin directory override", () => {
|
|
45
|
+
withCleanToolEnv(() => {
|
|
46
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "svn-agent-bin-"));
|
|
47
|
+
try {
|
|
48
|
+
for (const executable of ["svn.exe", "svnversion.exe", "svnadmin.exe", "dos2unix.exe", "unix2dos.exe"]) {
|
|
49
|
+
fs.writeFileSync(path.join(dir, executable), "");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
process.env.SVN_AGENT_BIN_DIR = dir;
|
|
53
|
+
|
|
54
|
+
expect(path.normalize(svnExecutable())).toBe(path.join(dir, "svn.exe"));
|
|
55
|
+
expect(path.normalize(svnVersionExecutable())).toBe(path.join(dir, "svnversion.exe"));
|
|
56
|
+
expect(path.normalize(svnAdminExecutable())).toBe(path.join(dir, "svnadmin.exe"));
|
|
57
|
+
expect(path.normalize(dos2UnixExecutable("dos2unix"))).toBe(path.join(dir, "dos2unix.exe"));
|
|
58
|
+
expect(path.normalize(dos2UnixExecutable("unix2dos"))).toBe(path.join(dir, "unix2dos.exe"));
|
|
59
|
+
} finally {
|
|
60
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("runs SVN commands non-interactively", async () => {
|
|
66
|
+
const run = await runSvn(["--version", "--quiet"], process.cwd());
|
|
67
|
+
|
|
68
|
+
expect(run.exitCode).toBe(0);
|
|
69
|
+
expect(run.args[0]).toBe("--non-interactive");
|
|
70
|
+
expect(run.command).toContain("--non-interactive");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("forces a stable C locale for child tools", async () => {
|
|
74
|
+
const run = await runExecutable(process.execPath, ["-e", "process.stdout.write(process.env.LC_ALL || '')"], {
|
|
75
|
+
cwd: process.cwd()
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(run.stdout).toBe("C");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("falls back to latin1 when child output is not valid UTF-8", async () => {
|
|
82
|
+
const run = await runExecutable(process.execPath, ["-e", "process.stdout.write(Buffer.from([0xe9]))"], {
|
|
83
|
+
cwd: process.cwd()
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(run.stdout).toBe("é");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("caps streaming stderr and marks the run truncated", async () => {
|
|
90
|
+
const run = await runExecutableStreamingLines(
|
|
91
|
+
process.execPath,
|
|
92
|
+
["-e", "process.stderr.write('x'.repeat(1000))"],
|
|
93
|
+
{ cwd: process.cwd(), stderrMaxBuffer: 16 },
|
|
94
|
+
() => undefined
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(run.exitCode).toBe(0);
|
|
98
|
+
expect(run.stderr.length).toBeLessThan(1000);
|
|
99
|
+
expect(run.stderr).toContain("[stderr truncated]");
|
|
100
|
+
expect(run.truncated).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("falls back to latin1 for streamed stdout lines that are not valid UTF-8", async () => {
|
|
104
|
+
const lines: string[] = [];
|
|
105
|
+
const run = await runExecutableStreamingLines(
|
|
106
|
+
process.execPath,
|
|
107
|
+
["-e", "process.stdout.write(Buffer.from([0x2b, 0xe9, 0x0a]))"],
|
|
108
|
+
{ cwd: process.cwd() },
|
|
109
|
+
(line) => lines.push(line)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
expect(run.exitCode).toBe(0);
|
|
113
|
+
expect(lines).toEqual(["+é"]);
|
|
114
|
+
expect(run.stdout).toBe("+é");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("settles streaming calls on timeout", async () => {
|
|
118
|
+
const started = Date.now();
|
|
119
|
+
const run = await runExecutableStreamingLines(
|
|
120
|
+
process.execPath,
|
|
121
|
+
["-e", "setInterval(() => {}, 1000)"],
|
|
122
|
+
{ cwd: process.cwd(), timeout: 50 },
|
|
123
|
+
() => undefined
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
expect(Date.now() - started).toBeLessThan(2000);
|
|
127
|
+
expect(run.timedOut).toBe(true);
|
|
128
|
+
expect(run.exitCode).toBeNull();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
function withCleanToolEnv(fn: () => void): void {
|
|
133
|
+
const saved = {
|
|
134
|
+
SVN_AGENT_BIN_DIR: process.env.SVN_AGENT_BIN_DIR,
|
|
135
|
+
SVN_AGENT_SVN_PATH: process.env.SVN_AGENT_SVN_PATH,
|
|
136
|
+
SVN_AGENT_DOS2UNIX_DIR: process.env.SVN_AGENT_DOS2UNIX_DIR
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
delete process.env.SVN_AGENT_BIN_DIR;
|
|
140
|
+
delete process.env.SVN_AGENT_SVN_PATH;
|
|
141
|
+
delete process.env.SVN_AGENT_DOS2UNIX_DIR;
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
fn();
|
|
145
|
+
} finally {
|
|
146
|
+
restoreEnv("SVN_AGENT_BIN_DIR", saved.SVN_AGENT_BIN_DIR);
|
|
147
|
+
restoreEnv("SVN_AGENT_SVN_PATH", saved.SVN_AGENT_SVN_PATH);
|
|
148
|
+
restoreEnv("SVN_AGENT_DOS2UNIX_DIR", saved.SVN_AGENT_DOS2UNIX_DIR);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function restoreEnv(name: string, value: string | undefined): void {
|
|
153
|
+
if (value === undefined) {
|
|
154
|
+
delete process.env[name];
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
process.env[name] = value;
|
|
159
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import { svnSelfCheck } from "../src/tools/selfcheck.js";
|
|
3
|
+
|
|
4
|
+
describe("svn self-check", () => {
|
|
5
|
+
it("reports package version, current release pointer, and bundled payload counts", async () => {
|
|
6
|
+
const check = await svnSelfCheck({});
|
|
7
|
+
|
|
8
|
+
expect(check.ok).toBe(true);
|
|
9
|
+
expect(check.server_version).toMatch(/^\d+\.\d+\.\d+$/);
|
|
10
|
+
expect(check.package_version).toBe(check.server_version);
|
|
11
|
+
expect(check.current_release).toBe(`v${check.server_version}`);
|
|
12
|
+
expect(check.current_matches_package).toBe(true);
|
|
13
|
+
expect(check.bin_file_count).toBe(48);
|
|
14
|
+
expect(check.dist_file_count).toBeGreaterThanOrEqual(60);
|
|
15
|
+
expect(check.release_prepare_available).toBe(true);
|
|
16
|
+
expect(check.clean_uses_node).toBe(true);
|
|
17
|
+
expect(check.toolchain_ok).toBe(true);
|
|
18
|
+
expect(check.startup_probe.svn.ok).toBe(true);
|
|
19
|
+
expect(check.startup_probe.dos2unix.ok).toBe(true);
|
|
20
|
+
expect(check.startup_probe.unix2dos.ok).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"rootDir": "./src",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"declaration": true,
|
|
16
|
+
"declarationMap": true,
|
|
17
|
+
"sourceMap": true,
|
|
18
|
+
"noImplicitReturns": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"noUncheckedIndexedAccess": true,
|
|
21
|
+
"exactOptionalPropertyTypes": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
"allowSyntheticDefaultImports": true,
|
|
24
|
+
"isolatedModules": true,
|
|
25
|
+
"incremental": false,
|
|
26
|
+
"tsBuildInfoFile": ".tsbuildinfo"
|
|
27
|
+
},
|
|
28
|
+
"include": ["src/**/*"],
|
|
29
|
+
"exclude": ["node_modules", "dist", "releases", "tests"]
|
|
30
|
+
}
|