diff options
| author | 2024-04-01 15:21:04 +0800 | |
|---|---|---|
| committer | 2024-04-01 15:21:04 +0800 | |
| commit | 2c218d91a3a797e97d607e6407f70cca603cf894 (patch) | |
| tree | 83da749b8ddfc45fdf635d3a08158f92bce4467b | |
| parent | a64f3878fb7e6bbe9f239c24332d4d9a3898dc52 (diff) | |
| download | ipm-2c218d91a3a797e97d607e6407f70cca603cf894.tar.gz ipm-2c218d91a3a797e97d607e6407f70cca603cf894.zip | |
feat(resolve): add lock deep resolve by dfs
| -rw-r--r-- | src/ipm/models/index.py | 27 | ||||
| -rw-r--r-- | src/ipm/models/ipk.py | 2 | ||||
| -rw-r--r-- | src/ipm/models/lock.py | 7 | ||||
| -rw-r--r-- | src/ipm/models/requirement.py | 7 | ||||
| -rw-r--r-- | src/ipm/utils/resolve.py | 30 |
5 files changed, 70 insertions, 3 deletions
diff --git a/src/ipm/models/index.py b/src/ipm/models/index.py index 0bac21e..f61c818 100644 --- a/src/ipm/models/index.py +++ b/src/ipm/models/index.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Any, Literal, Optional, Union +from typing import Any, List, Literal, Optional, Union, TYPE_CHECKING from ipm.const import INDEX_PATH from ipm.exceptions import LockLoadFailed from ipm.typing import Dict @@ -9,6 +9,9 @@ import tempfile import shutil import json +if TYPE_CHECKING: + from ipm.models.requirement import Requirement + class Yggdrasil: def __init__(self, index: str, uuid: str) -> None: @@ -100,10 +103,32 @@ class Yggdrasil: return distribution["hash"] def get_lastest_version(self, name: str) -> Optional[str]: + """从本地获取规则包最新版本""" if name not in self.packages: return None return self.packages[name]["latestVersion"] + def get_requirements(self, name: str) -> List["Requirement"]: + if not name in self.packages: + return [] + from ipm.models.requirement import Requirement + + res = [] + requirements = self.packages[name]["requirements"] + for requirement in requirements: + res.append( + Requirement( + requirement["name"], + requirement["version"], + url=requirement.get( + "url", + f"/packages/{requirement['name']}-{requirement['version']}.ipk", + ), + yggdrasil=self, + ) + ) + return res + @property def uuid(self) -> str: """世界树唯一标识""" diff --git a/src/ipm/models/ipk.py b/src/ipm/models/ipk.py index 1a1e99f..fc77ac3 100644 --- a/src/ipm/models/ipk.py +++ b/src/ipm/models/ipk.py @@ -98,7 +98,7 @@ class InfiniProject(InfiniPackage): requirement.add("yggdrasil", yggdrasil) if yggdrasil else None requirement.add("index", index) if index else None if not requirement: - raise ValueError("") + raise ValueError self._data["requirements"].update({name: requirement}) # type: ignore def unrequire(self, name: str) -> None: diff --git a/src/ipm/models/lock.py b/src/ipm/models/lock.py index 160db4d..439d978 100644 --- a/src/ipm/models/lock.py +++ b/src/ipm/models/lock.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING import tomlkit + if TYPE_CHECKING: from ipm.models import ipk from ipm.models.index import Yggdrasil @@ -135,6 +136,8 @@ class ProjectLock(IPMLock): def init_from_project( project: "ipk.InfiniProject", dist_path: Optional[Path] = None ) -> "ProjectLock": + from ipm.utils.resolve import get_requirements_by_project + lock = ProjectLock(dist_path or project._source_path) lock._data = tomlkit.document() @@ -146,7 +149,9 @@ class ProjectLock(IPMLock): lock._data.add("metadata", metadata) packages = tomlkit.aot() - for requirement in project.requirements: + requirements = get_requirements_by_project(project) + + for requirement in requirements: if requirement.is_local(): packages.append( tomlkit.item( diff --git a/src/ipm/models/requirement.py b/src/ipm/models/requirement.py index 223ac18..04e33cb 100644 --- a/src/ipm/models/requirement.py +++ b/src/ipm/models/requirement.py @@ -35,6 +35,13 @@ class Requirement: self.yggdrasil = yggdrasil self.hash = hash + def __eq__(self, __value: "Requirement") -> bool: + return ( + __value.name == self.name + and __value.version == self.version + and __value.yggdrasil.index == self.yggdrasil.index + ) + def is_local(self) -> bool: return bool(self.path) diff --git a/src/ipm/utils/resolve.py b/src/ipm/utils/resolve.py new file mode 100644 index 0000000..8e0c32d --- /dev/null +++ b/src/ipm/utils/resolve.py @@ -0,0 +1,30 @@ +from typing import List +from ipm.models.index import Yggdrasil +from ipm.models.ipk import InfiniProject +from ipm.models.requirement import Requirement + + +def get_requirements( + requirement: Requirement, resolved: List[str] = [] +) -> List[Requirement]: + requirements = {} + for req in requirement.yggdrasil.get_requirements(requirement.name): + if req.name in resolved: + continue + resolved.append(req.name) + requirements[req.name] = req + sub_reqs = get_requirements(req, resolved) + for sub_seq in sub_reqs: + requirements[sub_seq.name] = sub_seq + + return list(requirements.values()) + + +def get_requirements_by_project(project: InfiniProject) -> List[Requirement]: + requirements = {} + for requirement in project.requirements: + requirements[requirement.name] = requirement + reqs = get_requirements(requirement) + for req in reqs: + requirements[req.name] = req + return list(requirements.values()) |
