summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/colors.py2
-rw-r--r--src/options.py5
-rw-r--r--src/util.py20
-rw-r--r--src/verbs/install.py115
-rw-r--r--src/verbs/sync.py2
5 files changed, 114 insertions, 30 deletions
diff --git a/src/colors.py b/src/colors.py
index c05d49b..df22d30 100644
--- a/src/colors.py
+++ b/src/colors.py
@@ -29,3 +29,5 @@ BG_MAGENTA = esc(45)
BG_CYAN = esc(46)
BG_WHITE = esc(47)
BG_DEFAULT = esc(49)
+
+CLEAR_LINE = "\033[K"
diff --git a/src/options.py b/src/options.py
index 910b8a3..499f9e7 100644
--- a/src/options.py
+++ b/src/options.py
@@ -27,6 +27,11 @@ options = {
"flag" : True,
"desc" : "skip any checksum or signature verification"
},
+ "n": {
+ "name" : "no-deps",
+ "flag" : True,
+ "desc" : "do not resolve dependencies"
+ },
"v": {
"name" : "verbose",
"flag" : True,
diff --git a/src/util.py b/src/util.py
index 16df7bc..2411f1d 100644
--- a/src/util.py
+++ b/src/util.py
@@ -3,6 +3,7 @@ import requests
import colors
import time
import os
+import hashlib
DEFAULT_BAR_COLOR = colors.BLACK + colors.BG_CYAN
DEFAULT_BAR_COLOR_RESET = colors.BG_BLACK + colors.CYAN
@@ -25,8 +26,8 @@ def loading_bar(completed, total, text,
print(color + info, end="\r")
-
-
+def print_reset(text):
+ print(colors.RESET + text)
def curl(url):
r = requests.get(url)
@@ -36,6 +37,21 @@ def mkdir(path):
if not os.path.exists(path):
os.makedirs(path)
+def md5sum(data):
+ return hashlib.md5(data)
+
+def ask_confirmation(text, default=True, no_confirm=False):
+ yes = "Y" if default else "y"
+ no = "n" if default else "N"
+
+ if no_confirm:
+ reponse = "y" if default else "n"
+ print(f"{text} [{yes},{no}] {colors.RESET} {reponse}")
+ else:
+ reponse = input(f"{text} [{yes},{no}] " + colors.RESET)
+
+ return reponse.lower() == "y" or len(reponse) == 0
+
if __name__ == "__main__":
for i in range(1000):
loading_bar(i, 1000, "it is loading...")
diff --git a/src/verbs/install.py b/src/verbs/install.py
index 11a2183..0847b1d 100644
--- a/src/verbs/install.py
+++ b/src/verbs/install.py
@@ -4,11 +4,8 @@ import util
import colors
import time
-def find_package(query, repos, packages_dir):
- sources = []
- checksum = None
- requested_repo = None
+def find_package(query, repos, packages_dir, sources):
for repo in repos:
repo_dir = os.path.join(packages_dir, repo)
files = os.listdir(repo_dir)
@@ -17,13 +14,21 @@ def find_package(query, repos, packages_dir):
requested_repo = repo
with open(os.path.join(repo_dir, query)) as file:
checksum = file.readline().strip().split("=")[-1]
- sources = file.readline().strip().split("=")[-1].split()
- return checksum, sources, requested_repo
+ listed_sources = file.readline().strip().split("=")[-1].split()
+ found_sources = {
+ source: util.add_path(url, repo)
+ for source, url in sources.items()
+ if source in listed_sources
+ }
+ return checksum, found_sources, requested_repo
return None, [], None
def retrieve_package_info(sources, checksum, package_name,
verbose=False, skip_verification=False):
+
+ # TODO we may potentially do this a few times while resolving deps, might want to cache things here
+ # TODO actually use the ping times we made earlier to decide which source to pick
for source,url in sources.items():
package_info_url = util.add_path(url, package_name + ".xipkg.info")
status, response = util.curl(package_info_url)
@@ -43,14 +48,18 @@ def retrieve_package_info(sources, checksum, package_name,
def retrieve_package(sources, checksum, package_name,
verbose=False, skip_verification=False):
+
+ # TODO actually use the ping times we made earlier to decide which source to pick
+ # TODO actually save tar file, and add loading bar
for source,url in sources.items():
- package_info_url = util.add_path(url, package_name + ".xipkg.info")
+ package_info_url = util.add_path(url, package_name + ".xipkg")
status, response = util.curl(package_info_url)
if status == 200:
- info = parse_package_info(response)
- if info["CHECKSUM"] == checksum or skip_verification:
- return info
+ downloaded_checksum = util.md5sum(response)
+ print(downloaded_checksum, "compared to requested", checksum)
+ if downloaded_checksum == checksum or skip_verification:
+ return reponse
else:
if verbose:
print(colors.RED
@@ -67,11 +76,63 @@ def parse_package_info(packageinfo):
split = line.split("=")
if len(split) > 1:
info[split[0]] = "=".join(split[1:])
+
return info
-def resolve_dependencies(package_info):
- getpkgs = lambda deps: re.findall("[\(\s](\w)[\)\s]")
- package_info[""]
+def resolve_dependencies(package_info, config):
+ getpkgs = lambda deps: re.findall("\w*", deps)
+ deps = getpkgs(package_info["DEPS"])
+
+ deps = [
+ dep for dep in deps if len(dep) > 0
+ ]
+
+ return deps
+
+def find_all_dependencies(package_names, options, config):
+ # this is all assuming that the order of deps installed doesn't matter
+ to_check = [p for p in package_names]
+ all_deps = []
+
+ while len(to_check) > 0:
+ util.loading_bar(len(all_deps), len(all_deps) + len(to_check), "Resolving dependencies...")
+ dep = to_check.pop()
+
+ dep_checksum, dep_sources, dep_repo = find_package(dep, config["repos"], config["dir"]["packages"], config["sources"])
+ if dep_checksum is not None:
+ info = retrieve_package_info(
+ dep_sources, dep_checksum, dep,
+ verbose=options["v"], skip_verification=options["u"]
+ )
+
+ if len(info) > 0:
+ all_deps.append(dep)
+ deps = resolve_dependencies(info, config)
+ for dep in deps:
+ if not dep in all_deps:
+
+ if is_installed(dep, config):
+ print(colors.YELLOW + f"Package {query} has already been installed")
+ else:
+ to_check.append(dep)
+ else:
+ if options["v"]:
+ util.print_reset(colors.CLEAR_LINE + colors.RED + f"Failed to retrieve info for {query}")
+ else:
+ util.print_reset(colors.CLEAR_LINE + colors.RED + f"Failed to find package {dep}")
+
+ if len(all_deps) > 0:
+ util.loading_bar(len(all_deps), len(all_deps) + len(to_check), "Resolved dependencies")
+ print(colors.RESET)
+
+ # assuming that the latter packages are core dependencies
+ # we can reverse the array to reflect the more important packages to install
+ all_deps.reverse()
+ return all_deps
+
+def is_installed(package_name, config):
+ # TODO actually find out if its installed
+ return False
def install(args, options, config):
sources = config["sources"]
@@ -81,23 +142,21 @@ def install(args, options, config):
unsafe = options["u"]
packages_dir = config["dir"]["packages"]
- for query in args:
- # TODO FIRST CHECK IF ALREADY INSTALLED
- checksum, listed_sources, repo = find_package(query, repos, packages_dir)
+ to_install = args if options["n"] else find_all_dependencies(args, options, config)
- if checksum is not None:
- info = retrieve_package_info(
- {
- source: util.add_path(url, repo)
- for source, url in sources.items()
- if source in listed_sources
- }, checksum, query,
- verbose=v, skip_verification=unsafe
- )
+ if len(to_install) > 0:
+ print(colors.BLUE + "The following packages will be installed:")
+ print(end="\t")
+ for d in to_install:
+ print(colors.BLUE if d in args else colors.LIGHT_BLUE, d, end="")
+ print()
- print(info)
+ if util.ask_confirmation(colors.BLUE + "Continue?", no_confirm=options["y"]):
+ print("installed")
else:
- print(colors.RED + "Package not found")
- print(colors.RESET, end="")
+ print(colors.RED + "Action cancelled by user")
+ else:
+ print(colors.LIGHT_RED + "Nothing to do")
+
diff --git a/src/verbs/sync.py b/src/verbs/sync.py
index bd828ef..c534f4d 100644
--- a/src/verbs/sync.py
+++ b/src/verbs/sync.py
@@ -24,6 +24,7 @@ def sync_packages(repo, sources, verbose=False):
listed = list_packages(url + repo if url[-1] == "/" else f"/{repo}")
if len(listed) == 0 and verbose:
print(colors.BG_RED + f"No packages found in {source}/{repo}" + colors.RESET)
+
total += len(listed)
for p in listed:
if not p in packages:
@@ -67,6 +68,7 @@ def save_package_list(validated, location):
with open(package_file, "w") as file:
file.write("checksum=" + info["checksum"] + "\n")
file.write("sources=" + " ".join([source for source in info["sources"]]))
+ file.write("deps=" + " ".join([source for source in info["sources"]]))
###### !!! #######