mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 10:59:32 +01:00
chore: replace the em-dashes this release added with plain punctuation
The merged PRs (mostly #714's git fetch) added about 120 em-dashes in comments, docs, test names and three settings strings. Each one is now a comma, colon, semicolon or parentheses. The English settings strings in index.html and their i18n.js keys change together, and the zh-CN value for the fetch interval uses full-width parentheses instead of a double dash. The one left is the regex in constants.js that matches a dash typed as a word, which is behaviour, not punctuation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
de1aab9b86
commit
c04fa97f78
28 files changed
+91
-91
No files matched your search
@@ -222,7 +222,7 @@ describe('App Settings modal structure', () => {
|
||||
// The strip destructure is the other half: an aliased key here never reaches the settings PUT.
|
||||
expect(settingsUi).not.toMatch(/gitFetch(?:Enabled|IntervalSeconds):\s*_\w+/);
|
||||
|
||||
// Declared in the .strict() schema — an undeclared key 400s the whole settings PUT.
|
||||
// Declared in the .strict() schema: an undeclared key 400s the whole settings PUT.
|
||||
expect(SettingsUpdateSchema.safeParse({ gitFetchEnabled: true, gitFetchIntervalSeconds: 300 }).success).toBe(true);
|
||||
|
||||
// Off by default (only an explicit true loads as on), and an empty box falls back to the default interval.
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* @fileoverview The Git fetch interval rows (App Settings → Bottom bar, Session Options → Git) in Chinese
|
||||
* (zh-CN): each label and description runs through the real translator over the real index.html in JSDOM and
|
||||
* reads in Chinese with no English left beyond the product name and the technical names Git / git fetch, and
|
||||
* every new key — the save toast in session-ui.js included — is in the dictionary exactly once (a repeated key
|
||||
* every new key (the save toast in session-ui.js included) is in the dictionary exactly once (a repeated key
|
||||
* in the object literal silently replaces the first).
|
||||
*
|
||||
* The Git tab's Status row is not here: its text is written at runtime by updateGitFetchStatus and carries
|
||||
* data-i18n-skip, so translating it would rewrite the stamp the code builds. 'sec' is not a key either — only
|
||||
* data-i18n-skip, so translating it would rewrite the stamp the code builds. 'sec' is not a key either: only
|
||||
* whole unit words are ('hours'), so 'sec' stays as written.
|
||||
*
|
||||
* Port: N/A.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* @fileoverview The Git fetch interval scheduler (src/git-fetch-scheduler.ts): which sessions a tick runs,
|
||||
* and which it must not. Every rule is checked by calling `tick(now)` with an explicit clock, so nothing here
|
||||
* depends on fake timers or on how long a real tick takes — the scheduler owns no timers itself.
|
||||
* depends on fake timers or on how long a real tick takes: the scheduler owns no timers itself.
|
||||
*
|
||||
* The run belongs to the FOLDER, so these tests put two sessions on one folder and expect one fetch that
|
||||
* both see, and they check the tick's two bounds separately: one shared bound for the fetches of the whole
|
||||
* tick, and the folders bounded by a bound that cannot be the same semaphore. A folder is due when ANY session
|
||||
* open on it is due, so the order the sessions were read cannot decide it — that is checked in both orders.
|
||||
* open on it is due, so the order the sessions were read cannot decide it, and that is checked in both orders.
|
||||
* A run carries the trigger that caused it, and what is published says the run's, not the tick's.
|
||||
*
|
||||
* Port: N/A.
|
||||
@@ -62,7 +62,7 @@ type Harness = {
|
||||
/** The folders the tick actually ran, in the order they were picked, with the trigger the tick passed. */
|
||||
calls: Array<{ cwd: string; opts: GitFetchOptions; trigger: GitFetchTrigger }>;
|
||||
published: Array<{ id: string; status: GitFetchStatus }>;
|
||||
/** Every path the tick probed, in order — the probe has to happen before anything is fetched. */
|
||||
/** Every path the tick probed, in order: the probe has to happen before anything is fetched. */
|
||||
probed: string[];
|
||||
settings: GitFetchSettings;
|
||||
dockerReads: number;
|
||||
@@ -247,7 +247,7 @@ describe('who runs', () => {
|
||||
expect(h.calls.length).toBe(4);
|
||||
});
|
||||
|
||||
it('runs a session that turned itself on even while the app-wide switch is off — that is what a per-session switch has to mean', async () => {
|
||||
it('runs a session that turned itself on even while the app-wide switch is off: that is what a per-session switch has to mean', async () => {
|
||||
const h = harness([VIEW('plain'), VIEW('own', { gitFetchEnabled: true, gitFetchIntervalSeconds: 30 })], {
|
||||
settings: { enabled: false, intervalSeconds: 300 },
|
||||
});
|
||||
@@ -355,7 +355,7 @@ describe('one folder, one run', () => {
|
||||
expect(await h.scheduler.tick(15_000)).toBe(0);
|
||||
expect(h.published).toEqual([]);
|
||||
|
||||
// The short session is past its own interval, so the folder is fetched — once, for both. The run that
|
||||
// The short session is past its own interval, so the folder is fetched (once, for both). The run that
|
||||
// happens covers the long session's interval too, and both still get it because both are open on the
|
||||
// folder: publishing only the session that made the folder due would leave the other tab on a stale row.
|
||||
h.published.length = 0;
|
||||
@@ -410,7 +410,7 @@ describe('one folder, one run', () => {
|
||||
{
|
||||
// Every folder is handed the SAME limiter for its work, so that work cannot get its own bound: a
|
||||
// per-call bound would let 5 folders × 6 items run at once. The folders themselves are bounded by a
|
||||
// DIFFERENT bound, because one semaphore cannot serve both levels — a folder holding a slot and then
|
||||
// DIFFERENT bound, because one semaphore cannot serve both levels: a folder holding a slot and then
|
||||
// waiting for one for its own fetch is waiting on itself, and the folders that fill the bound are
|
||||
// exactly the ones blocking it. If the tick used one semaphore for both, this test would hang and fail
|
||||
// as a timeout rather than as an assertion.
|
||||
|
||||
+11
-11
@@ -1,24 +1,24 @@
|
||||
/**
|
||||
* @fileoverview Tests for the Git panel's Fetch button (src/git-fetch.ts): the only git command the Git panel
|
||||
* runs that writes, and the only one that can run without being asked — which is why it is a click, or an
|
||||
* runs that writes, and the only one that can run without being asked, which is why it is a click, or an
|
||||
* interval the user turned on, and why the writing and the hooks it can run are pinned here. Cloning and
|
||||
* worktree management write too, but they write when the user asked.
|
||||
*
|
||||
* Four halves, mirroring the module:
|
||||
*
|
||||
* 1. The PURE half — the fixed argv, the `-c` overrides the runner adds ahead of it, the ssh environment the
|
||||
* 1. The PURE half: the fixed argv, the `-c` overrides the runner adds ahead of it, the ssh environment the
|
||||
* runner refuses to override (`fetchEnvFor`), the failure classification, and the two reads the interval
|
||||
* scheduler depends on: what the settings say (`gitFetchSettingsFrom`) and what a run did
|
||||
* (`gitFetchStatusFrom`). No spawning.
|
||||
* 2. The IO half — a REAL git fetching a REAL local bare repo, so that "remote-tracking refs only" is
|
||||
* 2. The IO half: a REAL git fetching a REAL local bare repo, so that "remote-tracking refs only" is
|
||||
* proven against git's actual behavior: HEAD, the index and the working tree must be exactly what they
|
||||
* were while the remote-tracking ref moves. The rest of the half uses an injected runner over real
|
||||
* repositories on disk, because what is being pinned is WHICH repositories git is allowed to touch.
|
||||
* 3. The process group — a timed-out fetch has to take its `git-remote-http` helper with it, against a
|
||||
* 3. The process group: a timed-out fetch has to take its `git-remote-http` helper with it, against a
|
||||
* server that accepts and never answers, so the assertion is about what is still RUNNING after the answer
|
||||
* went out. A test that only checked the returned error would pass with the old `execFile` runner, which
|
||||
* signals the parent only.
|
||||
* 4. The join (`fetchWorkspaceOnce`) — one run per folder at a time, because two fetches in one clone
|
||||
* 4. The join (`fetchWorkspaceOnce`): one run per folder at a time, because two fetches in one clone
|
||||
* collide on git's ref lock, the bound is ONE limiter shared with the scheduler's tick rather than a bound
|
||||
* each run gets for itself, and the trigger a join reports is the joined run's, not the joiner's.
|
||||
*
|
||||
@@ -311,7 +311,7 @@ describe.skipIf(!gitPresent)('fetchGitWorkspaceOverview (real git)', () => {
|
||||
git(work, 'push', '-q', 'origin', 'main');
|
||||
|
||||
// A commit made elsewhere and pushed: work's origin/main cannot hear about it until a fetch runs.
|
||||
// This has to be a clone of origin, not a fresh init — a commit on its own root commit is no
|
||||
// This has to be a clone of origin, not a fresh init: a commit on its own root commit is no
|
||||
// descendant of what origin already holds, so pushing it is rejected as non-fast-forward.
|
||||
const other = join(dir, 'other');
|
||||
git(dir, 'clone', '-q', origin, 'other');
|
||||
@@ -441,7 +441,7 @@ interface Proc {
|
||||
}
|
||||
|
||||
/**
|
||||
* Every process on the machine, as /proc reports it — so this half can only run on Linux, and the fields are
|
||||
* Every process on the machine, as /proc reports it, so this half can only run on Linux, and the fields are
|
||||
* counted from the closing parenthesis because `comm` can hold spaces.
|
||||
*
|
||||
* Membership of the GROUP is what is checked, not parentage: a helper that outlives its parent stops being a
|
||||
@@ -496,8 +496,8 @@ describe.skipIf(!gitPresent)('runFetch (the whole tree, not just the git parent)
|
||||
const answered = runFetch(repo, buildFetchArgs(), { timeoutMs: 1_500 }).catch((e) => e);
|
||||
|
||||
// The tree has to be a tree before the timeout, or nothing is being proven: git itself, and the helper
|
||||
// it spawns for an http remote. The helper is a grandchild — `git fetch` runs `git remote-http`, which
|
||||
// spawns `git-remote-http` — so the group, not the parentage, is what proves it. Each process is
|
||||
// it spawns for an http remote. The helper is a grandchild (`git fetch` runs `git remote-http`, which
|
||||
// spawns `git-remote-http`), so the group, not the parentage, is what proves it. Each process is
|
||||
// remembered once found rather than re-scanned: after the kill the group is empty, and a test that kept
|
||||
// looking would report a tree it had already destroyed. The `git config` read the runner does first is
|
||||
// a `git` too, so the fetch is found by what it was asked to do.
|
||||
@@ -527,7 +527,7 @@ describe.skipIf(!gitPresent)('runFetch (the whole tree, not just the git parent)
|
||||
expect(err.code).toBe('ETIMEDOUT');
|
||||
expect(err.killed).toBe(true);
|
||||
|
||||
// The answer went out before the tree died — that is the whole point of the fix, and it is why the
|
||||
// The answer went out before the tree died: that is the whole point of the fix, and it is why the
|
||||
// escalation is given its own time here instead of being cancelled when the promise settles.
|
||||
const deadline = Date.now() + FETCH_KILL_ESCALATION_MS + 2_000;
|
||||
while (Date.now() < deadline && scanProc().some((p) => p.pgrp === parent!.pgrp)) await sleep(50);
|
||||
@@ -631,7 +631,7 @@ describe.skipIf(!gitPresent)('fetchWorkspaceOnce (the join)', () => {
|
||||
const first = fetchWorkspaceOnce(folder, { git: firstRunner }, 'interval');
|
||||
await runStarted; // the run is going, and still going
|
||||
|
||||
// A click while that run is working the folder: it joins, so it never touches git at all — not even the
|
||||
// A click while that run is working the folder: it joins, so it never touches git at all, not even the
|
||||
// resolver's own probe, because it does not resolve anything for itself.
|
||||
let joinerCalls = 0;
|
||||
const joinerRunner: GitRunner = async () => {
|
||||
|
||||
@@ -523,7 +523,7 @@ describe('POST /api/sessions/:id/git-fetch', () => {
|
||||
const { app } = await setup({ git: runner });
|
||||
const data = (await app.inject({ method: 'POST', url: '/api/sessions/test-session-1/git-fetch' })).json().data;
|
||||
expect(data.state).toBe('not-a-repo');
|
||||
// The resolver looked once and found nothing, so nothing was fetched — and never guessed a repository.
|
||||
// The resolver looked once and found nothing, so nothing was fetched, and it never guessed a repository.
|
||||
expect(fetches()).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -564,7 +564,7 @@ describe('POST /api/sessions/:id/git-fetch', () => {
|
||||
const second = app.inject({ method: 'POST', url: '/api/sessions/test-session-1/git-fetch' });
|
||||
// Assert the join BEFORE releasing the run: the lane entry goes away when the run finishes, so releasing
|
||||
// first would let the run complete before this request reached the lane, and it would then be entitled to
|
||||
// start its own fetch — a test that passes for the wrong reason. One tick of the loop is enough for both
|
||||
// start its own fetch: a test that passes for the wrong reason. One tick of the loop is enough for both
|
||||
// handlers to reach the lane while the run is still held open.
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
expect(fetches).toHaveLength(1); // one run, and the second request is waiting on it, not working
|
||||
@@ -593,7 +593,7 @@ describe('POST /api/sessions/:id/git-fetch', () => {
|
||||
const { app, ctx } = await setup({ git: runner });
|
||||
|
||||
// The interval tick got to this clone first. The click joins it, so the row the other tabs see has to name
|
||||
// the interval — the user clicked, but nothing this click did was a fetch. The request is left open, not
|
||||
// the interval: the user clicked, but nothing this click did was a fetch. The request is left open, not
|
||||
// awaited: awaiting it here would wait on the run this test is holding, and the test would wait on itself.
|
||||
const intervalRun = fetchWorkspaceOnce(dir, { git: runner }, 'interval');
|
||||
await runStarted;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* `POST /api/sessions/:id/git-fetch-settings` (session-routes.ts): the per-case half of the fetch interval
|
||||
* (src/git-fetch-scheduler.ts) — the case's own switch and its own interval. `null` on either half clears
|
||||
* (src/git-fetch-scheduler.ts): the case's own switch and its own interval. `null` on either half clears
|
||||
* that half so the app-wide setting applies again, and a body that names one row leaves the other as it was,
|
||||
* because the Session Options rows save on their own. Refused for remote and Docker cases, the same rule the
|
||||
* Git panel and the scheduler use. app.inject(), no port.
|
||||
|
||||
@@ -105,7 +105,7 @@ describe('Session Options modal structure', () => {
|
||||
expect(update).toContain('set-row-disabled');
|
||||
expect(update).toContain('el.disabled = follows');
|
||||
// Decided from BOTH fields: a half-choice means the session is not following, and the half that still
|
||||
// follows shows the app's value while the other shows its own — a switch-only check would gray out a live row.
|
||||
// follows shows the app's value while the other shows its own; a switch-only check would gray out a live row.
|
||||
expect(update).toMatch(
|
||||
/follows = session\.gitFetchEnabled === undefined && session\.gitFetchIntervalSeconds === undefined/
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Port: none (a pure function in a vm context — no browser, no server).
|
||||
// Port: none (a pure function in a vm context: no browser, no server).
|
||||
//
|
||||
// File paths with spaces in them (`OneDrive - Contoso/…`, `90 Sensitive/…`) were
|
||||
// cut at the first space by every path pattern, so the terminal and the response
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Port: none (pure functions + the link provider in a vm context — no browser, no server).
|
||||
// Port: none (pure functions + the link provider in a vm context: no browser, no server).
|
||||
//
|
||||
// Absolute file paths codex word-wrapped inside a markdown table cell were not
|
||||
// clickable: the first fragment has no extension and the continuation has no
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Port: none (pure functions + the link provider in a vm context — no browser, no server).
|
||||
// Port: none (pure functions + the link provider in a vm context: no browser, no server).
|
||||
//
|
||||
// Terminal URL links that stopped short.
|
||||
//
|
||||
|
||||
Reference in new issue
Block a user