Skip to content

Commit beaed86

Browse files
committed
Drop the pre-release .httk-project anchor detection arm
1 parent f032ba6 commit beaed86

3 files changed

Lines changed: 15 additions & 72 deletions

File tree

docs/projects.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -284,19 +284,6 @@ Run the shown `httk project import-v1 /path/to/project`. It reads
284284
`/path/to/project/ht.project/config`, copies the public keys, pins the readable
285285
legacy keys as trusted, and creates `/path/to/project/httk_project/`.
286286

287-
A pre-release v2 project containing `.httk-project/project.json` produces:
288-
289-
```console
290-
$ httk project show
291-
httk project: found a project anchor from a pre-release httk v2 ('.httk-project') at /path/to/project; rename it: mv /path/to/project/.httk-project /path/to/project/httk_project
292-
```
293-
294-
Apply the shown remedy from the project root:
295-
296-
```console
297-
mv .httk-project httk_project
298-
```
299-
300287
## Identity keys, pinning, and trust
301288

302289
A project owns one Ed25519 signing key. Its public half is recorded in

src/httk/core/project/anchor.py

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,41 +44,29 @@
4444

4545

4646
class LegacyProjectError(ValueError):
47-
"""Raised when discovery finds a legacy project directory.
47+
"""Raised when discovery finds an httk v1 ``ht.project`` directory.
4848
49-
Carries the offending directory as :attr:`root` and the legacy flavor as
50-
:attr:`kind` — ``"v1"`` for an httk v1 ``ht.project`` directory,
51-
``"prerelease"`` for a pre-release httk v2 ``.httk-project`` anchor — so a
52-
caller that deliberately handles one flavor (for example read-only
53-
verification of a v1 manifest) does not have to parse the message.
49+
Carries the offending directory as :attr:`root` so a caller that
50+
deliberately handles it (for example read-only verification of a v1
51+
manifest) does not have to parse the message.
5452
5553
:param message: Diagnostic explaining the legacy project and its remedy.
5654
:param root: Directory containing the legacy project marker.
57-
:param kind: Legacy flavor, either v1 or prerelease.
5855
"""
5956

60-
def __init__(self, message: str, *, root: Path, kind: str) -> None:
57+
def __init__(self, message: str, *, root: Path) -> None:
6158
super().__init__(message)
6259
self.root = root
63-
self.kind = kind
6460

6561

66-
def _legacy_project_error(candidate: Path, *, allow_v1: bool = False) -> LegacyProjectError | None:
62+
def _legacy_project_error(candidate: Path) -> LegacyProjectError | None:
6763
if (candidate / PROJECT_DIRECTORY / PROJECT_FILE).is_file():
6864
return None
69-
if not allow_v1 and (candidate / "ht.project").is_dir():
65+
if (candidate / "ht.project").is_dir():
7066
return LegacyProjectError(
7167
f"found an httk v1 project ('ht.project') at {candidate}; "
7268
f"create the httk v2 anchor with: httk project import-v1 {candidate}",
7369
root=candidate,
74-
kind="v1",
75-
)
76-
if (candidate / ".httk-project" / PROJECT_FILE).is_file():
77-
return LegacyProjectError(
78-
f"found a project anchor from a pre-release httk v2 ('.httk-project') at {candidate}; "
79-
f"rename it: mv {candidate}/.httk-project {candidate}/{PROJECT_DIRECTORY}",
80-
root=candidate,
81-
kind="prerelease",
8270
)
8371
return None
8472

@@ -87,13 +75,12 @@ def discover_project(start: str | os.PathLike[str] | None = None) -> Path | None
8775
"""Find the nearest project root, or refuse a legacy one, at or above *start*.
8876
8977
Discovery walks from start and its parents, treating a file start as its
90-
containing directory. If it finds a legacy marker, the exception identifies
91-
the required remedy: run httk project import-v1 PATH for ht.project, or
92-
rename .httk-project to httk_project for the pre-release anchor.
78+
containing directory. If it finds a legacy ht.project marker, the exception
79+
identifies the required remedy: run httk project import-v1 PATH.
9380
9481
:param start: Directory or file from which to begin the upward search, or None for the current directory.
9582
:return: Nearest project root, or None when no marker is found.
96-
:raises httk.core.project.LegacyProjectError: If discovery finds a v1 or pre-release project marker.
83+
:raises httk.core.project.LegacyProjectError: If discovery finds a v1 project marker.
9784
"""
9885

9986
path = Path.cwd() if start is None else Path(start)
@@ -114,7 +101,7 @@ def require_project(start: str | os.PathLike[str] | None = None) -> Path:
114101
115102
:param start: Directory or file from which to begin the upward search, or None for the current directory.
116103
:return: Nearest project root.
117-
:raises httk.core.project.LegacyProjectError: If discovery finds a v1 or pre-release project marker.
104+
:raises httk.core.project.LegacyProjectError: If discovery finds a v1 project marker.
118105
:raises ValueError: If no project marker is found.
119106
"""
120107

@@ -393,7 +380,7 @@ def initialize_project(
393380
:param description: Optional project description.
394381
:param manifest_exclusions: Relative paths excluded from project manifests.
395382
:return: Newly written project metadata.
396-
:raises httk.core.project.LegacyProjectError: If root contains a v1 or pre-release project marker.
383+
:raises httk.core.project.LegacyProjectError: If root contains a v1 project marker.
397384
"""
398385

399386
project = Path(root).expanduser().resolve()
@@ -454,7 +441,6 @@ def import_v1_project(
454441
:param name: Optional replacement project name.
455442
:return: Imported project metadata.
456443
:raises FileNotFoundError: If the legacy project directory does not exist.
457-
:raises httk.core.project.LegacyProjectError: If root contains an incompatible project anchor.
458444
"""
459445

460446
project = Path(root).expanduser().resolve()
@@ -465,12 +451,8 @@ def import_v1_project(
465451
parser.read(legacy / "config", encoding="utf-8")
466452
project_name = name if name is not None else str(parser.get("main", "project_name", fallback=project.name))
467453
# Importing v1 intentionally creates the v2 anchor beside its ht.project
468-
# directory, so the v1 flavor of the legacy check is waived here — and only
469-
# here, through the private unchecked initializer. A pre-release
470-
# .httk-project anchor is still refused with its rename remedy.
471-
error = _legacy_project_error(project, allow_v1=True)
472-
if error is not None:
473-
raise error
454+
# directory through the private unchecked initializer, so no legacy refusal
455+
# applies here.
474456
metadata = _initialize_project_unchecked(project, name=project_name)
475457
metadata["imported_from"] = str(legacy)
476458
public_keys: list[str] = []

tests/test_project.py

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,6 @@ def test_initialize_refuses_legacy_project_directories(tmp_path: Path) -> None:
8181
initialize_project(v1, name="v1")
8282
assert not (v1 / PROJECT_DIRECTORY).exists()
8383

84-
prerelease = tmp_path / "prerelease"
85-
(prerelease / ".httk-project").mkdir(parents=True)
86-
(prerelease / ".httk-project" / PROJECT_FILE).write_text("{}", encoding="utf-8")
87-
with pytest.raises(LegacyProjectError, match="rename it: mv"):
88-
initialize_project(prerelease, name="prerelease")
89-
assert not (prerelease / PROJECT_DIRECTORY).exists()
90-
9184

9285
def test_discover_walks_upward_and_require_refuses_when_absent(tmp_path: Path) -> None:
9386
project = tmp_path / "root"
@@ -183,16 +176,6 @@ def test_import_v1_creates_the_anchor_and_adopts_legacy_keys(tmp_path: Path) ->
183176
assert (project / PROJECT_DIRECTORY / "keys" / "legacy-public" / "old.pub").is_file()
184177

185178

186-
def test_discover_refuses_a_pre_release_v2_anchor(tmp_path: Path) -> None:
187-
anchor = tmp_path / ".httk-project"
188-
anchor.mkdir()
189-
(anchor / PROJECT_FILE).write_text("{}", encoding="utf-8")
190-
191-
with pytest.raises(LegacyProjectError, match="rename it: mv") as error:
192-
discover_project(tmp_path)
193-
assert f"mv {tmp_path}/.httk-project {tmp_path}/httk_project" in str(error.value)
194-
195-
196179
# ---------------------------------------------------------------------------
197180
# The umbrella command line
198181
# ---------------------------------------------------------------------------
@@ -254,20 +237,11 @@ def test_bare_project_command_prints_help(tmp_path) -> None:
254237
assert command([], context) == 0
255238

256239

257-
def test_legacy_error_carries_root_and_kind(tmp_path: Path) -> None:
240+
def test_legacy_error_carries_root(tmp_path: Path) -> None:
258241
(tmp_path / "ht.project").mkdir()
259242
with pytest.raises(LegacyProjectError) as error:
260243
discover_project(tmp_path)
261244
assert error.value.root == tmp_path
262-
assert error.value.kind == "v1"
263-
264-
prerelease = tmp_path / "elsewhere"
265-
(prerelease / ".httk-project").mkdir(parents=True)
266-
(prerelease / ".httk-project" / PROJECT_FILE).write_text("{}", encoding="utf-8")
267-
with pytest.raises(LegacyProjectError) as error:
268-
discover_project(prerelease)
269-
assert error.value.root == prerelease
270-
assert error.value.kind == "prerelease"
271245

272246

273247
def test_initialize_project_has_no_legacy_bypass_parameter() -> None:

0 commit comments

Comments
 (0)