Implement sjnetpkg 0.1.0, a Git-based package manager
Packages are ordinary Git repositories carrying a sjnetpkg.toml, so sjnetpkg only needs to resolve, clone, track and run them instead of inventing an archive format or build system. This adds the v0.1 CLI (install from registry or Git URL, remove, list/inspect, registry update, run) on top of the Python standard library, together with a test suite. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from sjnetpkg import config, registry
|
||||
|
||||
|
||||
class LoadRegistryTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self.paths = config.get_paths(Path(self._tmp.name) / ".sjnetpkg")
|
||||
self.paths.home.mkdir(parents=True)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self._tmp.cleanup()
|
||||
|
||||
def test_loads_packages(self) -> None:
|
||||
self.paths.registry.write_text(
|
||||
'[packages.cool-tool]\nrepo = "https://example.com/cool-tool.git"\n'
|
||||
'[packages.other]\nrepo = "https://example.com/other.git"\n'
|
||||
)
|
||||
self.assertEqual(
|
||||
registry.load_registry(self.paths),
|
||||
{
|
||||
"cool-tool": "https://example.com/cool-tool.git",
|
||||
"other": "https://example.com/other.git",
|
||||
},
|
||||
)
|
||||
|
||||
def test_missing_registry_raises(self) -> None:
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.load_registry(self.paths)
|
||||
|
||||
def test_invalid_toml_raises(self) -> None:
|
||||
self.paths.registry.write_text("not = = toml\n")
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.load_registry(self.paths)
|
||||
|
||||
def test_missing_packages_table_raises(self) -> None:
|
||||
self.paths.registry.write_text('something = "else"\n')
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.load_registry(self.paths)
|
||||
|
||||
def test_entry_without_repo_raises(self) -> None:
|
||||
self.paths.registry.write_text('[packages.cool-tool]\nname = "cool-tool"\n')
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.load_registry(self.paths)
|
||||
|
||||
def test_resolve_returns_repo(self) -> None:
|
||||
self.assertEqual(
|
||||
registry.resolve({"cool-tool": "https://example.com/cool-tool.git"}, "cool-tool"),
|
||||
"https://example.com/cool-tool.git",
|
||||
)
|
||||
|
||||
def test_resolve_unknown_raises(self) -> None:
|
||||
with self.assertRaises(registry.PackageNotFoundError):
|
||||
registry.resolve({}, "missing")
|
||||
|
||||
|
||||
class DownloadRegistryTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self._tmp.name)
|
||||
self.paths = config.get_paths(self.root / ".sjnetpkg")
|
||||
self.paths.home.mkdir(parents=True)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self._tmp.cleanup()
|
||||
|
||||
def _source(self, name: str, content: str) -> str:
|
||||
path = self.root / name
|
||||
path.write_text(content, encoding="utf-8")
|
||||
return path.as_uri()
|
||||
|
||||
def test_download_replaces_local_registry(self) -> None:
|
||||
url = self._source(
|
||||
"remote.toml",
|
||||
'[packages.cool-tool]\nrepo = "https://example.com/cool-tool.git"\n',
|
||||
)
|
||||
registry.download_registry(url, self.paths.registry)
|
||||
self.assertEqual(
|
||||
registry.load_registry(self.paths),
|
||||
{"cool-tool": "https://example.com/cool-tool.git"},
|
||||
)
|
||||
|
||||
def test_failed_download_keeps_existing_registry(self) -> None:
|
||||
self.paths.registry.write_text('[packages.old]\nrepo = "https://example.com/old.git"\n')
|
||||
missing = (self.root / "missing.toml").as_uri()
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.download_registry(missing, self.paths.registry)
|
||||
self.assertEqual(
|
||||
registry.load_registry(self.paths),
|
||||
{"old": "https://example.com/old.git"},
|
||||
)
|
||||
|
||||
def test_invalid_download_keeps_existing_registry(self) -> None:
|
||||
self.paths.registry.write_text('[packages.old]\nrepo = "https://example.com/old.git"\n')
|
||||
url = self._source("broken.toml", "this = = invalid\n")
|
||||
with self.assertRaises(registry.RegistryError):
|
||||
registry.download_registry(url, self.paths.registry)
|
||||
self.assertEqual(
|
||||
registry.load_registry(self.paths),
|
||||
{"old": "https://example.com/old.git"},
|
||||
)
|
||||
|
||||
def test_update_uses_configured_url(self) -> None:
|
||||
url = self._source(
|
||||
"remote.toml",
|
||||
'[packages.cool-tool]\nrepo = "https://example.com/cool-tool.git"\n',
|
||||
)
|
||||
config.ensure_home(self.paths)
|
||||
self.paths.config.write_text(f'registry = "{url}"\n', encoding="utf-8")
|
||||
registry.update_registry(self.paths)
|
||||
self.assertEqual(
|
||||
registry.load_registry(self.paths),
|
||||
{"cool-tool": "https://example.com/cool-tool.git"},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user