"""Regression tests for Issue #973: validated cross-repository canonical roots.""" from __future__ import annotations import os import shutil import tempfile import unittest from pathlib import Path import subprocess import gitea_config import namespace_workspace_binding as nwb import canonical_repository_root as crr class TestIssue973RecognizedEnvKeys(unittest.TestCase): """Test recognized environment variable keys under #973.""" def test_recognized_gitea_env_keys(self): for key in ( "GITEA_CANONICAL_REPOSITORY_ROOT", "GITEA_REVIEWER_WORKTREE", "GITEA_MERGER_WORKTREE", "GITEA_MCP_SESSION_STATE_TTL_HOURS", ): self.assertIn(key, gitea_config.RECOGNIZED_GITEA_ENV_KEYS) def test_get_unconsumed_gitea_env_overrides_ignores_recognized(self): env = { "GITEA_CANONICAL_REPOSITORY_ROOT": "/some/path", "GITEA_REVIEWER_WORKTREE": "/some/reviewer/path", "GITEA_MERGER_WORKTREE": "/some/merger/path", "GITEA_MCP_SESSION_STATE_TTL_HOURS": "24", "GITEA_UNRECOGNIZED_FOO_VAR": "bar", } unconsumed = gitea_config.get_unconsumed_gitea_env_overrides(env) self.assertNotIn("GITEA_CANONICAL_REPOSITORY_ROOT", unconsumed) self.assertNotIn("GITEA_REVIEWER_WORKTREE", unconsumed) self.assertNotIn("GITEA_MERGER_WORKTREE", unconsumed) self.assertNotIn("GITEA_MCP_SESSION_STATE_TTL_HOURS", unconsumed) self.assertIn("GITEA_UNRECOGNIZED_FOO_VAR", unconsumed) class TestIssue973CrossRepoCanonicalRoots(unittest.TestCase): """Test workspace binding and canonical root validation for cross-repo namespaces.""" def setUp(self): self._tmp = tempfile.TemporaryDirectory() self.tmp_dir = os.path.realpath(self._tmp.name) # Create simulated installation root self.install_root = os.path.join(self.tmp_dir, "Gitea-Tools") os.makedirs(self.install_root) subprocess.run(["git", "init", "-b", "master"], cwd=self.install_root, check=True) # Create simulated target repository root self.target_root = os.path.join(self.tmp_dir, "mcp-control-plane") os.makedirs(self.target_root) subprocess.run(["git", "init", "-b", "master"], cwd=self.target_root, check=True) # Create branches/ directory and a valid worktree in target repository self.target_branches = os.path.join(self.target_root, "branches") os.makedirs(self.target_branches) self.target_worktree = os.path.join(self.target_branches, "rev-pr-99") os.makedirs(self.target_worktree) # Create git common dir linking target_worktree to target_root dot_git_file = os.path.join(self.target_worktree, ".git") git_dir_target = os.path.join(self.target_root, ".git", "worktrees", "rev-pr-99") os.makedirs(git_dir_target, exist_ok=True) with open(dot_git_file, "w") as f: f.write(f"gitdir: {git_dir_target}\n") with open(os.path.join(git_dir_target, "commondir"), "w") as f: f.write("../../..\n") def tearDown(self): self._tmp.cleanup() def test_valid_cross_repo_canonical_root(self): ctx = nwb.resolve_namespace_mutation_context( role_kind="reviewer", worktree_path=self.target_worktree, process_project_root=self.install_root, env={}, configured_canonical_root=self.target_root, ) self.assertEqual(ctx["canonical_repo_root"], self.target_root) self.assertTrue(ctx["roots_aligned"]) self.assertTrue(ctx["canonical_root_assessment"]["proven"]) def test_nonexistent_configured_canonical_root(self): nonexistent = os.path.join(self.tmp_dir, "nonexistent-repo") ctx = nwb.resolve_namespace_mutation_context( role_kind="reviewer", worktree_path=self.target_worktree, process_project_root=self.install_root, env={}, configured_canonical_root=nonexistent, ) self.assertFalse(ctx["roots_aligned"]) self.assertFalse(ctx["canonical_root_assessment"]["proven"]) self.assertTrue(any("does not exist" in r for r in ctx["canonical_root_assessment"]["reasons"])) def test_non_git_configured_canonical_root(self): non_git = os.path.join(self.tmp_dir, "non-git-dir") os.makedirs(non_git) ctx = nwb.resolve_namespace_mutation_context( role_kind="reviewer", worktree_path=self.target_worktree, process_project_root=self.install_root, env={}, configured_canonical_root=non_git, ) self.assertFalse(ctx["roots_aligned"]) self.assertFalse(ctx["canonical_root_assessment"]["proven"]) self.assertTrue(any("not a git repository" in r for r in ctx["canonical_root_assessment"]["reasons"])) def test_git_common_directory_membership_matching(self): valid, err = nwb.verify_git_common_directory_membership( self.target_worktree, self.target_root ) self.assertTrue(valid, err) self.assertIsNone(err) def test_git_common_directory_membership_foreign_repo_blocks(self): # Foreign worktree created under install_root foreign_wt = os.path.join(self.install_root, "branches", "foreign-wt") os.makedirs(foreign_wt) dot_git_file = os.path.join(foreign_wt, ".git") git_dir_install = os.path.join(self.install_root, ".git", "worktrees", "foreign-wt") os.makedirs(git_dir_install, exist_ok=True) with open(dot_git_file, "w") as f: f.write(f"gitdir: {git_dir_install}\n") with open(os.path.join(git_dir_install, "commondir"), "w") as f: f.write("../../..\n") valid, err = nwb.verify_git_common_directory_membership( foreign_wt, self.target_root ) self.assertFalse(valid) self.assertIn("does not belong", err) def test_reviewer_worktree_outside_branches_blocks(self): outside_wt = os.path.join(self.target_root, "outside_branches_wt") os.makedirs(outside_wt) assessment = nwb.assess_namespace_mutation_workspace( role_kind="reviewer", worktree_path=outside_wt, worktree=None, process_project_root=self.install_root, env={}, configured_canonical_root=self.target_root, ) self.assertTrue(assessment["block"]) self.assertTrue(any("is not under" in r for r in assessment["reasons"])) if __name__ == "__main__": unittest.main()