summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author苏向夜 <fu050409@163.com>2024-01-21 17:50:15 +0800
committer苏向夜 <fu050409@163.com>2024-01-21 17:50:15 +0800
commita184d2f54c84e13c3ec45d7fdba9d36727931bf2 (patch)
tree2afd6aed5a830fa2e0f431bf0862e7924db8fa1b
parent3ebc89dfeb77cf90b1760fbb17780bf896681b7e (diff)
downloadipm-a184d2f54c84e13c3ec45d7fdba9d36727931bf2.tar.gz
ipm-a184d2f54c84e13c3ec45d7fdba9d36727931bf2.zip
:sparkles: feat(api): improve install methods
-rw-r--r--src/ipm/api.py19
-rw-r--r--src/ipm/const.py1
-rw-r--r--src/ipm/models/ipk.py4
-rw-r--r--src/ipm/models/lock.py64
-rw-r--r--src/ipm/utils/loader.py36
5 files changed, 114 insertions, 10 deletions
diff --git a/src/ipm/api.py b/src/ipm/api.py
index ea55afb..3853faa 100644
--- a/src/ipm/api.py
+++ b/src/ipm/api.py
@@ -2,8 +2,9 @@ from pathlib import Path
from .typing import StrPath
from .utils import freeze, urlparser, loader
from .models.ipk import InfiniPackage, InfiniFrozenPackage
+from .models.lock import PackageLock
from .exceptions import FileTypeMismatch, TomlLoadFailed, FileNotFoundError
-from .const import INDEX, SRC_HOME
+from .const import INDEX, STORAGE, SRC_HOME
from .logging import info, success, warning, error
import toml
@@ -69,12 +70,14 @@ def install(uri: str, index: str = "", echo: bool = False) -> None:
SRC_HOME.mkdir(parents=True, exist_ok=True)
index = index or INDEX
+ lock = PackageLock()
if uri.isalpha():
+ # TODO
...
elif urlparser.is_valid_url(uri):
filename = uri.rstrip("/").split("/")[-1]
- ipk = loader.load(
+ temp_ipk = loader.load_from_remote(
"temp",
uri.rstrip("/").rsplit("/")[0],
filename,
@@ -86,11 +89,19 @@ def install(uri: str, index: str = "", echo: bool = False) -> None:
raise FileNotFoundError("给定的 URI 路径不存在!")
if uri.endswith(".ipk"):
- info("安装中...", echo)
- ipk = extract(Path(uri).resolve(), SRC_HOME, echo)
+ temp_ipk = loader.load_from_local(path)
else:
raise FileTypeMismatch("文件类型与预期[.ipk]不匹配.")
+ if lock.has_ipk(temp_ipk.name):
+ raise # TODO
+
+ info(f"开始安装[{temp_ipk.name}]中...", echo)
+ ipk = extract(STORAGE / temp_ipk.source_path, SRC_HOME, echo)
+ info("正在处理全局包锁...")
+ lock.add(ipk, dump=True)
+ info("全局锁已处理完毕.")
+
success(f"包[{ipk.name}]成功安装在[{ipk.source_path}].", echo)
diff --git a/src/ipm/const.py b/src/ipm/const.py
index 439903a..d3dbcbf 100644
--- a/src/ipm/const.py
+++ b/src/ipm/const.py
@@ -7,6 +7,7 @@ DEBUG = False
INDEX = "https://ipm.hydroroll.team/index/"
IPM_PATH = Path.home() / ".ipm"
SRC_HOME = IPM_PATH / "src"
+STORAGE = IPM_PATH / "storage"
# 文本参数
ATTENSION = """# This file is @generated by IPM.
diff --git a/src/ipm/models/ipk.py b/src/ipm/models/ipk.py
index c4577e9..ef6f649 100644
--- a/src/ipm/models/ipk.py
+++ b/src/ipm/models/ipk.py
@@ -1,4 +1,5 @@
from pathlib import Path
+from . import lock
from ..typing import List, Dict, Literal
from ..exceptions import SyntaxError, TomlLoadFailed
@@ -38,6 +39,8 @@ class InfiniPackage:
requirements: dict
dependencies: dict
+ lock: lock.ProjectLock
+
def __init__(self, path: str | Path = ".") -> None:
self.source_path = Path(path).resolve()
toml_path = self.source_path / "infini.toml"
@@ -59,6 +62,7 @@ class InfiniPackage:
self.requirements = data_load["requirements"]
self.dependencies = data_load["dependencies"]
+ # self.lock = ProjectLock
@property
def default_name(self) -> str:
diff --git a/src/ipm/models/lock.py b/src/ipm/models/lock.py
new file mode 100644
index 0000000..78f4921
--- /dev/null
+++ b/src/ipm/models/lock.py
@@ -0,0 +1,64 @@
+from pathlib import Path
+from abc import ABCMeta
+from . import ipk
+from ..typing import Dict, List, StrPath, Any
+from ..const import IPM_PATH, ATTENSION
+from ..exceptions import SyntaxError
+
+import toml
+
+
+class IpmLock(metaclass=ABCMeta):
+ metadata: Dict[str, str]
+ packages: List[Dict[str, Any]]
+ source_path: Path
+
+ def __init__(self, source_path: StrPath = IPM_PATH / "inifni.lock") -> None:
+ IPM_PATH.mkdir(parents=True, exist_ok=True)
+ self.source_path = source_path
+ self.load()
+
+ def load(self):
+ if not self.source_path.exists():
+ self.source_path.write_text(ATTENSION)
+ self.packages = {}
+ else:
+ loaded_data = toml.load(self.source_path.open("r", encoding="utf-8"))
+ self.packages = loaded_data["package"]
+
+ def dumps(self) -> dict:
+ return {"metadata": self.metadata, "packages": self.packages}
+
+ def dump(self) -> str:
+ return toml.dump(self.source_path.open("w+", encoding="utf-8"))
+
+
+class PackageLock(IpmLock):
+ """全局包锁"""
+
+ def __init__(self) -> None:
+ super().__init__()
+
+ def add(self, ipk: "ipk.InfiniPackage", dump: bool = False) -> str:
+ self.packages.append({"name": ipk.name, "version": ipk.version})
+ return self.dump() if dump else ""
+
+ def remove(self, name: str) -> None:
+ name = name.strip()
+ for package in self.packages:
+ if "name" not in package.keys():
+ raise SyntaxError("异常的锁文件!")
+ if package["name"] == name:
+ self.packages.remove(package)
+ return
+
+ def has_ipk(self, name: str) -> bool:
+ name = name.strip()
+ for package in self.packages:
+ if package["name"] == name:
+ return True
+ return False
+
+
+class ProjectLock:
+ ...
diff --git a/src/ipm/utils/loader.py b/src/ipm/utils/loader.py
index 6c1bf25..18d98ac 100644
--- a/src/ipm/utils/loader.py
+++ b/src/ipm/utils/loader.py
@@ -1,27 +1,51 @@
from pathlib import Path
from .freeze import extract_ipk
-from ..const import SRC_HOME
+from ..const import SRC_HOME, STORAGE
from ..models.ipk import InfiniPackage
import requests
import tempfile
+import shutil
-def load(name: str, baseurl: str = "", filename: str = "") -> InfiniPackage:
+def load_from_remote(name: str, baseurl: str = "", filename: str = "") -> InfiniPackage:
ipk_bytes = requests.get(baseurl.rstrip("/") + "/" + filename).content
hash_bytes = requests.get(baseurl.rstrip("/") + "/" + filename + ".hash").content
temp_dir = tempfile.TemporaryDirectory()
temp_path = Path(temp_dir.name).resolve()
- ipk_file = (temp_path / f"{name}.ipk").open("w+b")
+ ipk_path = temp_path / f"{name}.ipk"
+ ipk_file = ipk_path.open("w+b")
ipk_file.write(ipk_bytes)
ipk_file.close()
- hash_file = (temp_path / f"{name}.ipk.hash").open("w+b")
+ hash_path = temp_path / f"{name}.ipk.hash"
+ hash_file = hash_path.open("w+b")
hash_file.write(hash_bytes)
hash_file.close()
- ipk = extract_ipk(ipk_file, SRC_HOME)
+ temp_ipk = extract_ipk(ipk_file, temp_path)
+ move_to = STORAGE / temp_ipk.name
+ move_to.mkdir(parents=True, exist_ok=True)
+
+ shutil.copy2(ipk_file, move_to)
+ shutil.copy2(hash_file, move_to)
+
+ temp_dir.cleanup()
+ return temp_ipk
+
+
+def load_from_local(source_path: Path) -> InfiniPackage:
+ temp_dir = tempfile.TemporaryDirectory()
+ temp_path = Path(temp_dir.name).resolve()
+
+ temp_ipk = extract_ipk(source_path, temp_path)
+ move_to = STORAGE / temp_ipk.name
+ move_to.mkdir(parents=True, exist_ok=True)
+
+ shutil.copy2(source_path, move_to)
+ shutil.copy2(source_path.parent / (source_path.name + ".hash"), move_to)
+
temp_dir.cleanup()
- return ipk
+ return temp_ipk