mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 18:39:33 +01:00
fix(cases): skip the cleanup when git never ran, and refuse Docker workspaces
A direct clone whose git-slot wait timed out came back with no spawnError, so the cleanup emptied a folder git never touched. GitRun now says whether git started and the cleanup requires it. Cloning into a folder at or inside a Docker case workspace is refused, as git status, fetch and worktrees do, since git would run the new repository's hooks and filters on the host.
This commit is contained in:
1 parent
086249a386
commit
b549a66aa3
5 files changed
+127
-12
No files matched your search
@@ -51,6 +51,8 @@ import {
|
||||
probeGitRemote,
|
||||
} from '../../git-clone.js';
|
||||
import type { GitRemoteProbe, GitUrlParse } from '../../git-clone.js';
|
||||
import { isPathWithin } from '../../git-worktrees.js';
|
||||
import { defaultDockerWorkspaces } from './git-status-routes.js';
|
||||
import { generateClaudeMd } from '../../templates/claude-md.js';
|
||||
import { prepareNewCasePath } from '../case-path.js';
|
||||
import {
|
||||
@@ -147,6 +149,9 @@ const APP_VERSION = (() => {
|
||||
* would copy another user's workspace into the caller's own (the same escape
|
||||
* `/api/cases/link` is admin-only for).
|
||||
*/
|
||||
const DOCKER_CLONE_REFUSAL =
|
||||
'Cloning is not available into a folder inside a Docker case workspace: a container can write there, and git would run the new repository’s hooks and filters on this machine. Clone outside the workspace and link it, or clone from inside the container.';
|
||||
|
||||
const LOCAL_CLONE_ADMIN_ONLY =
|
||||
'Cloning from a local path is admin-only in multi-user mode. Use a repository URL instead.';
|
||||
|
||||
@@ -790,6 +795,27 @@ export function registerCaseRoutes(
|
||||
}
|
||||
}
|
||||
|
||||
// git runs the new repository's hooks and filters on THIS machine once the clone finishes, and a container
|
||||
// with the workspace bind-mounted can write both while it fetches. Like git status, fetch and worktrees,
|
||||
// never clone at or inside a Docker case workspace. Fails closed when the Docker case list cannot be read.
|
||||
try {
|
||||
const roots = await Promise.all(
|
||||
(await defaultDockerWorkspaces()).map((root) => fs.realpath(root).catch(() => resolve(root)))
|
||||
);
|
||||
// A custom folder is already symlink-resolved; the default one is judged through its real cases dir.
|
||||
const dest =
|
||||
customPath !== undefined ? casePath : join(await fs.realpath(casesDir).catch(() => casesDir), name);
|
||||
if (roots.some((root) => isPathWithin(dest, root))) {
|
||||
return createErrorResponse(ApiErrorCode.INVALID_INPUT, DOCKER_CLONE_REFUSAL);
|
||||
}
|
||||
} catch {
|
||||
reply.code(503);
|
||||
return createErrorResponse(
|
||||
ApiErrorCode.OPERATION_FAILED,
|
||||
'Could not read the Docker case list, so Codeman cannot tell whether that folder is a Docker case workspace. Try again.'
|
||||
);
|
||||
}
|
||||
|
||||
const clone = await cloneRepository({
|
||||
repository: parsed.repository,
|
||||
destination: casePath,
|
||||
|
||||
Reference in new issue
Block a user