fix(migrate): validate workspace connection targets

This commit is contained in:
Mohamed Boudra
2026-07-19 01:10:18 +02:00
parent e61c06706c
commit faccbaae59
4 changed files with 78 additions and 5 deletions
@@ -83,6 +83,41 @@ test("reports an unknown workspace state by its exact value", () => {
});
});
test("does not adopt an existing worktree on a different branch", () => {
const repo = createRepository("wrong-worktree-branch", null);
execFileSync("git", ["commit", "--allow-empty", "-m", "initial"], {
cwd: repo,
env: {
...process.env,
GIT_AUTHOR_NAME: "Paseo Test",
GIT_AUTHOR_EMAIL: "test@paseo.local",
GIT_COMMITTER_NAME: "Paseo Test",
GIT_COMMITTER_EMAIL: "test@paseo.local",
},
});
execFileSync("git", ["branch", "recorded-branch"], { cwd: repo });
const inspected = inspectCatalog({
repos: [repoRecord("repo", repo)],
workspaces: [
{
id: "workspace-wrong-branch",
repoId: "repo",
branch: "recorded-branch",
state: "ready",
path: repo,
archiveCommit: null,
},
],
});
expect(inspected.projects[0]?.workspaces[0]).toMatchObject({
sourceId: "workspace-wrong-branch",
disposition: "invalid",
notices: [{ code: "invalid-worktree" }],
});
});
function createRepository(name: string, settings: string | null): string {
const repo = mkdtempSync(path.join(os.tmpdir(), `paseo-inspect-${name}-`));
cleanup.push(repo);
@@ -112,7 +112,7 @@ function inspectWorkspace(
}
if (workspace.path && isDirectory(workspace.path)) {
const valid = isLinkedWorktree(repo.rootPath, workspace.path);
const valid = isLinkedWorktree(repo.rootPath, workspace.path, workspace.branch);
return {
sourceId: workspace.id,
state: "ready",
@@ -126,7 +126,9 @@ function inspectWorkspace(
: [
notice(
"invalid-worktree",
`Skipped ${workspace.path}: not linked to ${repo.rootPath}.`,
workspace.branch
? `Skipped ${workspace.path}: not linked to ${repo.rootPath} on recorded branch ${workspace.branch}.`
: `Skipped ${workspace.path}: not linked to ${repo.rootPath}.`,
),
],
};
@@ -174,14 +176,21 @@ function isGitRepository(rootPath: string): boolean {
}
}
function isLinkedWorktree(rootPath: string, workspacePath: string): boolean {
function isLinkedWorktree(
rootPath: string,
workspacePath: string,
expectedBranch: string | null,
): boolean {
try {
const rootCommon = resolveGitPath(rootPath, git(rootPath, ["rev-parse", "--git-common-dir"]));
const workspaceCommon = resolveGitPath(
workspacePath,
git(workspacePath, ["rev-parse", "--git-common-dir"]),
);
return realpathSync(rootCommon) === realpathSync(workspaceCommon);
if (realpathSync(rootCommon) !== realpathSync(workspaceCommon)) return false;
if (!expectedBranch) return true;
const actualBranch = git(workspacePath, ["symbolic-ref", "--short", "HEAD"]);
return actualBranch === expectedBranch.replace(/^refs\/heads\//, "");
} catch {
return false;
}