mirror of
https://github.com/daijro/camoufox.git
synced 2026-09-08 16:01:00 +00:00
fix(python): reach the fetch path when the installed build is below the floor
Raising CONSTRAINTS.MIN_VERSION is how this library has always forced a browser upgrade (beta.12 -> beta.15 -> beta.17 -> beta.18 -> beta.19); the floor only became 'alpha.1' incidentally, in an unrelated PR. That left the branch dead, and it had rotted: camoufox_path() probed INSTALL_DIR/version.json, which only the pre-multiversion flat layout ever wrote. With a versioned install below the floor it raised FileNotFoundError instead of falling through to a fetch, so raising the floor would have crashed every existing user rather than upgrading them. Treat a missing root version.json as "no legacy install here" so the caller falls through to CamoufoxFetcher().install() as intended. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
850a5751e6
commit
da67775257
@@ -755,6 +755,22 @@ def installed_verstr() -> str:
|
||||
return Version.from_path(active).full_string
|
||||
|
||||
|
||||
def _root_install_supported() -> bool:
|
||||
"""
|
||||
Whether INSTALL_DIR's root holds a supported build.
|
||||
|
||||
Only the pre-multiversion flat layout wrote version.json at the root; the
|
||||
versioned layout keeps it under browsers/<repo>/<version>/. A missing root
|
||||
version.json means "no legacy install here", so the caller should fall
|
||||
through to a fetch rather than raise. The alpha.1 floor masked this: no
|
||||
install was ever unsupported, so this branch was never reached.
|
||||
"""
|
||||
try:
|
||||
return Version.from_path().is_supported()
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
|
||||
def camoufox_path(download_if_missing: bool = True) -> Path:
|
||||
"""
|
||||
Full path to the active camoufox folder
|
||||
@@ -787,7 +803,7 @@ def camoufox_path(download_if_missing: bool = True) -> Path:
|
||||
f"{active_display} is not installed. " f"Please run `camoufox fetch` to install."
|
||||
)
|
||||
|
||||
elif os.path.exists(INSTALL_DIR) and Version.from_path().is_supported():
|
||||
elif os.path.exists(INSTALL_DIR) and _root_install_supported():
|
||||
return INSTALL_DIR
|
||||
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
"""Regression coverage for raising the supported browser floor.
|
||||
|
||||
Raising ``CONSTRAINTS.MIN_VERSION`` is how the library forces an existing
|
||||
install to upgrade when it can no longer talk to the old browser. That path
|
||||
had been dead since the floor was dropped to ``alpha.1``, and it hid a bug:
|
||||
``camoufox_path`` probed ``INSTALL_DIR/version.json``, which only the
|
||||
pre-multiversion flat layout ever wrote, so a below-floor versioned install
|
||||
raised ``FileNotFoundError`` instead of falling through to a fetch.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from camoufox import multiversion, pkgman
|
||||
from camoufox.exceptions import UnsupportedVersion
|
||||
|
||||
|
||||
def _install(tmp_path, monkeypatch, layout, build, floor):
|
||||
"""Build an install dir in the given layout and point the library at it."""
|
||||
root = tmp_path / "cache"
|
||||
root.mkdir()
|
||||
(root / ".0.5_FLAG").write_text("")
|
||||
(root / "repo_cache.json").write_text("{}")
|
||||
|
||||
if layout == "versioned":
|
||||
relative = f"browsers/official/152.0.4-{build}"
|
||||
(root / "config.json").write_text(json.dumps({"active_version": relative}))
|
||||
version_dir = root / relative
|
||||
version_dir.mkdir(parents=True)
|
||||
else:
|
||||
(root / "config.json").write_text("{}")
|
||||
version_dir = root
|
||||
(version_dir / "version.json").write_text(
|
||||
json.dumps({"version": "152.0.4", "build": build})
|
||||
)
|
||||
|
||||
for module in (pkgman, multiversion):
|
||||
monkeypatch.setattr(module, "INSTALL_DIR", root)
|
||||
monkeypatch.setattr(multiversion, "BROWSERS_DIR", root / "browsers")
|
||||
monkeypatch.setattr(multiversion, "CONFIG_FILE", root / "config.json")
|
||||
monkeypatch.setattr(multiversion, "COMPAT_FLAG", root / ".0.5_FLAG")
|
||||
monkeypatch.setattr(pkgman, "VERSION_MIN", pkgman.Version(build=floor))
|
||||
return root
|
||||
|
||||
|
||||
@pytest.mark.parametrize("layout", ["versioned", "legacy"])
|
||||
def test_below_floor_install_is_reported_as_outdated(tmp_path, monkeypatch, layout):
|
||||
"""A build under the floor must report as outdated, never as missing."""
|
||||
_install(tmp_path, monkeypatch, layout, build="beta.29", floor="beta.30")
|
||||
|
||||
with pytest.raises(UnsupportedVersion):
|
||||
pkgman.camoufox_path(download_if_missing=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("layout", ["versioned", "legacy"])
|
||||
def test_at_floor_install_is_kept(tmp_path, monkeypatch, layout):
|
||||
"""A build at the floor is still served, in either layout."""
|
||||
root = _install(tmp_path, monkeypatch, layout, build="beta.30", floor="beta.30")
|
||||
|
||||
resolved = pkgman.camoufox_path(download_if_missing=False)
|
||||
|
||||
expected = root if layout == "legacy" else root / "browsers/official/152.0.4-beta.30"
|
||||
assert resolved == expected
|
||||
|
||||
|
||||
def test_below_floor_install_triggers_a_fetch(tmp_path, monkeypatch):
|
||||
"""The default path upgrades the install instead of raising."""
|
||||
root = _install(tmp_path, monkeypatch, "versioned", build="beta.29", floor="beta.30")
|
||||
installed = []
|
||||
|
||||
class StubFetcher:
|
||||
def install(self):
|
||||
installed.append(True)
|
||||
relative = "browsers/official/152.0.4-beta.30"
|
||||
version_dir = root / relative
|
||||
version_dir.mkdir(parents=True)
|
||||
(version_dir / "version.json").write_text(
|
||||
json.dumps({"version": "152.0.4", "build": "beta.30"})
|
||||
)
|
||||
(root / "config.json").write_text(json.dumps({"active_version": relative}))
|
||||
|
||||
monkeypatch.setattr(pkgman, "CamoufoxFetcher", StubFetcher)
|
||||
|
||||
resolved = pkgman.camoufox_path()
|
||||
|
||||
assert installed == [True]
|
||||
assert resolved == root / "browsers/official/152.0.4-beta.30"
|
||||
|
||||
|
||||
def test_root_probe_tolerates_the_versioned_layout(tmp_path, monkeypatch):
|
||||
"""The root probe reports False, rather than raising, with no root file."""
|
||||
root = tmp_path / "cache"
|
||||
root.mkdir()
|
||||
monkeypatch.setattr(pkgman, "INSTALL_DIR", root)
|
||||
|
||||
assert pkgman._root_install_supported() is False
|
||||
Reference in New Issue
Block a user