aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author苏向夜 <fu050409@163.com>2024-03-28 19:31:12 +0800
committer苏向夜 <fu050409@163.com>2024-03-28 19:31:12 +0800
commit57bfd47bf8fc6604428b3fbfb0a8523f0e926d67 (patch)
tree031db06afb0e44f36fbf830fafebfdffef6bf777
parentcc7779d8821210dcc358992e43a667822afd14db (diff)
downloadipm-57bfd47bf8fc6604428b3fbfb0a8523f0e926d67.tar.gz
ipm-57bfd47bf8fc6604428b3fbfb0a8523f0e926d67.zip
feat(index): implement index apis
-rw-r--r--src/ipm/models/index.py88
1 files changed, 58 insertions, 30 deletions
diff --git a/src/ipm/models/index.py b/src/ipm/models/index.py
index 4c9c38b..607f7a2 100644
--- a/src/ipm/models/index.py
+++ b/src/ipm/models/index.py
@@ -1,74 +1,102 @@
from pathlib import Path
+from typing import Any, List, Literal, Optional
from ipm.const import INDEX_PATH
from ipm.exceptions import LockLoadFailed
from ipm.models.lock import PackageLock
+from ipm.typing import Dict
-import tomlkit
import requests
import tempfile
import shutil
+import json
class Yggdrasil:
- """此对象内所有方法均为示例方法,可以按照需求和开发习惯进行微调"""
-
- def __init__(self, index: str) -> None:
+ def __init__(self, index: str, uuid: str) -> None:
self.index = index.rstrip("/") + "/"
+ self._source_path = INDEX_PATH / uuid
self._data = self.read()
- def read(self) -> tomlkit.TOMLDocument:
- """示例方法,读取一个本地的世界树索引文件,这里使用toml只是作为样例"""
+ def read(self) -> Dict:
if not self._source_path.exists():
self._source_path.parent.mkdir(parents=True, exist_ok=True)
- return tomlkit.document()
- return tomlkit.load(self._source_path.open("r", encoding="utf-8"))
+ return {}
+ return json.load(self._source_path.open("r", encoding="utf-8"))
def dump(self) -> None:
- """示例方法,将修改保存在本地"""
- tomlkit.dump(self._data, self._source_path.open("w", encoding="utf-8"))
+ json.dump(self._data, self._source_path.open("w", encoding="utf-8"))
+
+ @staticmethod
+ def try_loads(path: Path) -> Dict | Literal[False]:
+ try:
+ return json.loads(path.read_text(encoding="utf-8"))
+ except Exception as e:
+ print(e)
+ return False
@staticmethod
def check(source_path: Path):
"""检查一个索引文件是否合法"""
- raise NotImplementedError
+ if not (packages := Yggdrasil.try_loads(source_path)):
+ return False
+ return packages
- def sync(self):
- """示例方法,下载或同步索引文件"""
+ @staticmethod
+ def init(index: str) -> "Yggdrasil":
lock_bytes = requests.get(
- self.index + "infini.lock"
- ).content # 索引文件地址,这里的lock仅作示例
+ index.rstrip("/") + "/" + "json/packages.json"
+ ).content
temp_dir = tempfile.TemporaryDirectory()
temp_path = Path(temp_dir.name).resolve()
- temp_lock_path = temp_path / "infini.lock" # 本地索引文件地址,这里的lock仅作示例
+ temp_lock_path = temp_path / "packages.json"
temp_lock_file = temp_lock_path.open("wb")
temp_lock_file.write(lock_bytes)
temp_lock_file.close()
- Yggdrasil.check(temp_lock_path) # 检查索引文件合法性
-
- temp_lock = PackageLock(temp_lock_path)
+ if not (packages := Yggdrasil.check(temp_lock_path)):
+ raise LockLoadFailed(f"地址 [red]{index}[/] 不是合法的世界树服务器.")
- if "uuid" not in temp_lock.metadata.keys():
+ if "uuid" not in packages["metadata"].keys():
temp_dir.cleanup()
- raise LockLoadFailed(f"地址[{self.index}]不是合法的世界树服务器.")
+ raise LockLoadFailed(f"地址[{index}]不是合法的世界树服务器.")
+ uuid = packages["metadata"]["uuid"]
- self._source_path = INDEX_PATH / temp_lock.metadata["uuid"]
- self._source_path.mkdir(parents=True, exist_ok=True)
-
- shutil.copy2(temp_lock_path, self._source_path)
+ source_path = INDEX_PATH / uuid
+ shutil.copy2(temp_lock_path, source_path)
temp_dir.cleanup()
- def get_url(self, name: str, version: str) -> str:
+ lock = PackageLock()
+ lock.update_index(index, uuid, str(source_path))
+ return Yggdrasil(index, uuid)
+
+ def sync(self):
+ yggdrasil = Yggdrasil.init(self.index)
+ self._source_path = yggdrasil._source_path
+ self._data = yggdrasil._data
+
+ def get_url(self, name: str, version: str) -> Optional[str]:
"""从本地读取规则包下载链接"""
- raise NotImplementedError
+ if name not in self.packages:
+ return None
+ for distribution in self.packages[name]["distributions"]:
+ if distribution["version"] == version:
+ return distribution["download_url"]
- def get_hash(self, name: str, version: str) -> str:
+ def get_hash(self, name: str, version: str) -> Optional[str]:
"""从本地获取规则包哈希值"""
- raise NotImplementedError
+ if name not in self.packages:
+ return None
+ for distribution in self.packages[name]["distributions"]:
+ if distribution["version"] == version:
+ return distribution["hash"]
@property
def uuid(self) -> str:
"""世界树唯一标识"""
- raise NotImplementedError
+ return self._data["metadata"]["uuid"]
+
+ @property
+ def packages(self) -> Dict[str, Any]:
+ return self._data["packages"]