mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-11 10:57:07 +00:00
fix(migrate): validate workspace connection targets
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user