aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/ipm/api.py37
-rw-r--r--src/ipm/utils/version.py49
2 files changed, 83 insertions, 3 deletions
diff --git a/src/ipm/api.py b/src/ipm/api.py
index d1e0133..1eefb52 100644
--- a/src/ipm/api.py
+++ b/src/ipm/api.py
@@ -1,9 +1,15 @@
from pathlib import Path
from .typing import StrPath
from .utils import freeze, urlparser, loader
-from .exceptions import FileTypeMismatch, TomlLoadFailed, FileNotFoundError
from .const import INDEX, INDEX_PATH, STORAGE, SRC_HOME
from .logging import info, success, warning, error
+from .exceptions import (
+ FileTypeMismatch,
+ TomlLoadFailed,
+ FileNotFoundError,
+ PackageExsitsError,
+)
+from .utils.version import require_update
from .models.ipk import InfiniProject, InfiniFrozenPackage
from .models.lock import PackageLock
from .models.index import Yggdrasil
@@ -67,7 +73,13 @@ def extract(
return freeze.extract_ipk(source_path, dist_path, echo)
-def install(uri: str, index: str = "", echo: bool = False) -> None:
+def install(
+ uri: str,
+ index: str = "",
+ upgrade: bool = False,
+ force: bool = False,
+ echo: bool = False,
+) -> None:
info("正在初始化 IPM 环境...", echo)
SRC_HOME.mkdir(parents=True, exist_ok=True)
@@ -113,7 +125,26 @@ def install(uri: str, index: str = "", echo: bool = False) -> None:
raise FileTypeMismatch("文件类型与预期[.ipk]不匹配.")
if lock.has_package(ifp.name):
- raise # TODO
+ exists_version = lock.get_package(ifp.name)["version"]
+ if require_update(exists_version, ifp.version):
+ if not upgrade:
+ raise PackageExsitsError(
+ f"包[{ifp.name}]版本[{exists_version}]已经安装了, 使用[--upgrade]参数进行升级."
+ )
+ else:
+ info(f"发现已经安装的[{ifp.name}={exists_version}], 卸载中...")
+ uninstall(ifp.name, confirm=True, echo=echo)
+ success(f"[{ifp.name}={exists_version}]卸载完成...")
+ else:
+ if not force:
+ raise PackageExsitsError(
+ f"已经安装了[{ifp.name}]版本[{exists_version}], 使用[--force]参数进行强制覆盖."
+ )
+ else:
+ info(f"发现已经安装的[{ifp.name}={exists_version}], 卸载中...")
+ uninstall(ifp.name, confirm=True, echo=echo)
+ success(f"[{ifp.name}={exists_version}]卸载完成...")
+ lock.load(auto_completion=True)
info(f"开始安装[{ifp.name}]中...", echo)
ipk = extract(STORAGE / ifp.name / ifp.default_name, SRC_HOME, echo)
diff --git a/src/ipm/utils/version.py b/src/ipm/utils/version.py
new file mode 100644
index 0000000..6088d1c
--- /dev/null
+++ b/src/ipm/utils/version.py
@@ -0,0 +1,49 @@
+import re
+
+
+def require_update(old_version: str, new_version: str):
+ regex = r"^(\d+)\.(\d+)\.(\d+)(.*?)?(\d+?)?$"
+
+ old_tuple = re.match(regex, old_version)
+ new_tuple = re.match(regex, new_version)
+
+ old_tuple_main = tuple(map(int, filter(None, old_tuple.group(1, 2, 3))))
+ new_tuple_main = tuple(map(int, filter(None, new_tuple.group(1, 2, 3))))
+
+ new_length = len(list(filter(None, new_tuple.groups())))
+ old_length = len(list(filter(None, old_tuple.groups())))
+
+ if old_length == 5:
+ old_pre_release = old_tuple.group(4)[0]
+ old_pre_version = int(old_tuple.group(5))
+ elif old_length == 3:
+ old_pre_release = "s"
+ old_pre_version = 1
+ else:
+ return False
+
+ if new_length == 5:
+ new_pre_release = new_tuple.group(4)[0]
+ new_pre_version = int(new_tuple.group(5))
+ elif new_length == 3:
+ new_pre_release = "s"
+ new_pre_version = 1
+ else:
+ return False
+
+ if old_tuple_main < new_tuple_main:
+ return True
+ elif old_tuple_main > new_tuple_main:
+ return False
+ elif old_tuple_main == new_tuple_main:
+ if old_pre_release < new_pre_release:
+ return True
+ elif old_pre_release > new_pre_release:
+ return False
+ elif old_pre_release == new_pre_release:
+ if old_pre_version < new_pre_version:
+ return True
+ elif old_pre_version > new_pre_version:
+ return False
+ elif old_pre_version == new_pre_version:
+ return False