aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author苏向夜 <fu050409@163.com>2024-03-29 18:40:27 +0800
committer苏向夜 <fu050409@163.com>2024-03-29 18:40:27 +0800
commit5100cb9ace4e0f47a6846c03e39dd6be07266286 (patch)
treee5e594f730caa5621b558cd9d3f48e3c0e8a0ccb /src
parentaec2cb2b27309b485e81c67aec6a97fb8b7666ef (diff)
downloadipm-5100cb9ace4e0f47a6846c03e39dd6be07266286.tar.gz
ipm-5100cb9ace4e0f47a6846c03e39dd6be07266286.zip
feat(api): add sync, install api
Diffstat (limited to 'src')
-rw-r--r--src/ipm/__main__.py24
-rw-r--r--src/ipm/api.py108
2 files changed, 121 insertions, 11 deletions
diff --git a/src/ipm/__main__.py b/src/ipm/__main__.py
index 809c602..6e24b00 100644
--- a/src/ipm/__main__.py
+++ b/src/ipm/__main__.py
@@ -211,6 +211,30 @@ def doc(
@main.command()
+def sync():
+ """同步依赖环境"""
+ try:
+ if api.sync(Path.cwd(), echo=True):
+ tada()
+ except IPMException as err:
+ error(str(err), echo=True)
+ finally:
+ status.stop()
+
+
+@main.command()
+def install():
+ """安装规则包环境"""
+ try:
+ if api.install(Path.cwd(), echo=True):
+ tada()
+ except IPMException as err:
+ error(str(err), echo=True)
+ finally:
+ status.stop()
+
+
+@main.command()
def update():
"""更新 Infini 依赖"""
raise NotImplementedError
diff --git a/src/ipm/api.py b/src/ipm/api.py
index dca7975..f7a99a5 100644
--- a/src/ipm/api.py
+++ b/src/ipm/api.py
@@ -2,6 +2,7 @@ from datetime import datetime
from pathlib import Path
from typing import Optional
+from ipm.const import INDEX
from ipm.models.lock import PackageLock, ProjectLock
from ipm.project.env import new_virtualenv
from ipm.project.toml_file import (
@@ -11,11 +12,12 @@ from ipm.project.toml_file import (
remove_yggdrasil,
)
from ipm.typing import StrPath
-from ipm.utils import freeze
+from ipm.utils import freeze, loader
from ipm.utils.git import get_user_name_email, git_init, git_tag
from ipm.logging import confirm, status, update, info, success, warning, error, ask
from ipm.exceptions import (
EnvironmentError,
+ ProjectError,
TomlLoadFailed,
FileNotFoundError,
NameError,
@@ -240,13 +242,17 @@ def build(target_path: StrPath, echo: bool = False) -> Optional[InfiniFrozenPack
def extract(
- source_path: StrPath, dist_path: Optional[StrPath] = None, echo: bool = False
-) -> Optional[InfiniProject]:
+ source_path: StrPath,
+ hash: Optional[str] = None,
+ dist_path: Optional[StrPath] = None,
+ echo: bool = False,
+) -> bool:
info("解压缩规则包...", echo)
dist_path = (
Path(dist_path).resolve() if dist_path else Path(source_path).resolve().parent
)
- return freeze.extract_ipk(source_path, dist_path, None, echo)
+ freeze.extract_ipk(source_path, dist_path, hash=hash)
+ return True
def yggdrasil_add(
@@ -290,24 +296,38 @@ def require(
echo: bool = False,
) -> bool:
info(f"新增规则包依赖: [bold green]{name}[/bold green]", echo)
- status.start()
- status.update("检查环境中...")
+ update("检查环境中...", echo)
if not (toml_path := Path(target_path).joinpath("infini.toml")).exists():
raise FileNotFoundError(
f"文件 [green]infini.toml[/green] 尚未被初始化, 你可以使用[bold green]`ipm init`[/bold green]来初始化项目."
)
project = InfiniProject(toml_path.parent)
+ global_lock = PackageLock()
success("环境检查完毕.", echo)
+ update("检查世界树中...", echo)
+ ygd = (
+ Yggdrasil.init(index or INDEX)
+ if not global_lock.has_index(index or INDEX)
+ else global_lock.get_yggdrasil_by_index(index or INDEX)
+ )
+ if not ygd:
+ raise ProjectError("世界树检查失败!")
+
splited_name = name.split("==") # TODO 支持 >= <= > < 标识
name = splited_name[0]
if len(splited_name) > 1:
version = splited_name[1]
else:
- version = "*"
+ version = ygd.get_lastest_version(name)
+
+ if not version:
+ raise ProjectError(f"无法找到一个匹配 [red]{name}[/] 的版本。")
+
+ check(target_path, echo=echo)
- status.update("处理 Infini 项目依赖锁...")
+ update("处理 Infini 项目依赖锁...", echo)
project.require(
name,
version=version,
@@ -317,7 +337,7 @@ def require(
)
project.dump()
success("项目文件写入完成.", echo)
- check(target_path, echo=echo)
+
# sync()
success("规则包依赖新增完成.", echo)
return True
@@ -407,13 +427,79 @@ def remove(target_path: StrPath, name: str, echo: bool = False):
return True
-def sync(target_path: StrPath, echo: bool = False) -> bool: ...
+def sync(target_path: StrPath, echo: bool = False) -> bool:
+ info(f"同步依赖环境...", echo)
+ update("检查环境中...", echo)
+ if not (toml_path := Path(target_path).joinpath("infini.toml")).exists():
+ raise FileNotFoundError(
+ f"文件 [green]infini.toml[/green] 尚未被初始化, 你可以使用[bold green]`ipm init`[/bold green]来初始化项目."
+ )
+ InfiniProject(toml_path.parent)
+ lock = ProjectLock(target_path)
+ global_lock = PackageLock()
+ if not shutil.which("pdm"):
+ raise EnvironmentError(
+ "IPM 未能在环境中找到 [bold green]PDM[/] 安装, 请确保 PDM 在环境中被正确安装. "
+ "你可以使用`[bold green]pipx install pdm[/]`来安装此包管理器."
+ )
+ success("环境检查完毕.", echo)
+
+ update("同步依赖环境中...", echo)
+ for requirement in lock.requirements:
+ if not requirement.is_local():
+ if global_lock.has_frozen_package(requirement.name, requirement.version):
+ continue
+ update(
+ f"下载 [bold green]{requirement.name}=={requirement.version}[/]...",
+ echo,
+ )
+ ifp = loader.load_from_remote(
+ requirement.name,
+ requirement.yggdrasil.index.rstrip("/") + (requirement.url or ""),
+ requirement.hash or "",
+ )
+ global_lock.add_frozen_package(
+ requirement.name,
+ requirement.version,
+ requirement.hash or "",
+ requirement.yggdrasil.index,
+ str(ifp._source_path),
+ )
+ success(
+ f"[bold green]{requirement.name} {requirement.version}[/] 安装完成!",
+ echo,
+ )
+ success("依赖环境同步完毕!", echo)
+ return True
+
+
+def install(target_path: StrPath, echo: bool = False) -> bool:
+ info("安装规则表环境中...", echo)
+ update("检查环境中...", echo)
+ if not (toml_path := Path(target_path).joinpath("infini.toml")).exists():
+ raise FileNotFoundError(
+ f"文件 [green]infini.toml[/green] 尚未被初始化, 你可以使用[bold green]`ipm init`[/bold green]来初始化项目."
+ )
+ InfiniProject(toml_path.parent)
+ lock = ProjectLock(target_path)
+ global_lock = PackageLock()
+ if not shutil.which("pdm"):
+ raise EnvironmentError(
+ "IPM 未能在环境中找到 [bold green]PDM[/] 安装, 请确保 PDM 在环境中被正确安装. "
+ "你可以使用`[bold green]pipx install pdm[/]`来安装此包管理器."
+ )
+ success("环境检查完毕.", echo)
+
+ check(target_path, echo)
+ sync(target_path, echo)
+
+ return True
def doc(target_path: StrPath, type: str, dist: StrPath, echo: bool = False) -> bool:
info("构建项目文档...", echo)
if type.lower() != "vue":
- raise EnvironmentError("Only supports for Vue!")
+ raise EnvironmentError("目前仅支持 Vue!")
update("准备环境中...", echo)
if not (toml_path := Path(target_path).joinpath("infini.toml")).exists():