Skip to content

Commit

Permalink
icm install: initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Obijuan committed Jun 18, 2024
1 parent 7b6d03a commit 6c43a9d
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"type": "debugpy",
"request": "launch",
"program": "icm-run.py",
"args": ["install"],
"args": ["install","iceK"],
//"console": "internalConsole",
"console": "integratedTerminal",
"justMyCode": true,
Expand Down
9 changes: 7 additions & 2 deletions icm/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ def info():


@cli.command()
def install():
@click.argument("coltag", nargs=1)
@click.option(
"-d", "--dev", is_flag=True, help="Install latest development version"
)
def install(coltag, dev):
"""Install collections"""
cmd_install.main()

cmd_install.main(coltag, dev)
164 changes: 149 additions & 15 deletions icm/commands/cmd_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import zipfile
import os
import sys
import re
from pathlib import Path

import requests
Expand All @@ -29,6 +30,7 @@ class Collection:
GITHUB_PREFIX = "/archive/refs/"
GITHUB_TYPE_DEV = "heads/"
GITHUB_TYPE_VER = "tags/"
PACKAGEJSON = "/raw/main/package.json"

def __init__(self, folders: commons.Folders) -> None:
self.folders = folders
Expand Down Expand Up @@ -82,6 +84,20 @@ def url(self, name: str, version="") -> str:
# -- Return the url
return url

def package_url(self, name: str) -> str:
"""Return the url of the package.json file for the given
collection
* name: Collection name (Ex. "iceK")
"""
# -- Example of url for the iceK collection:
# https://github.com/FPGAwars/iceK/raw/main/package.json

# -- Construct the URL
url = f"{self.GITHUB_FPGAWARS}{name}{self.PACKAGEJSON}"

# -- Return the URL
return url

def nametag(self, name: str, version=""):
"""Return the collection name+tag:
* version Given:
Expand Down Expand Up @@ -134,6 +150,23 @@ def download(self, url: str, destfile: Path):
# Update pogress bar
pbar.update(len(chunk))

def download_package(self, url: str) -> object: # Or None:
"""Download the package.json as an object
url: package.json url
Returns: The package.json as an object
or None if there was an error
"""
# -- Generate an http request
response = requests.get(url, timeout=10)

# -- Check the status. If not ok, exit!
if response.status_code != 200:
return None

# -- Return the package object
package = response.json()
return package

# -- Uncompress the collection zip file
def uncompress(self, zip_file: Path):
"""Uncompress the given zip file. The destination folder is
Expand All @@ -160,26 +193,128 @@ def uncompress(self, zip_file: Path):
# -- Update progress bar!
pbar.update(1)

def parse_coltag(self, coltag: str) -> dict: # or | None:
"""Parse a collection name with optional tag version
Ex: "iceK@0.1.4"
Return:
None: There is an error
result: Dictionary with the calculated values
result['name']: Collection name
result['version']: Collection version (it could be "")
"""
# -- Pattern for parsing strings in the format <name>[@<version>]
pattern = r"^(?P<name>[a-zA-Z0-9]+)(@(?P<version>\d+\.\d+(\.\d+)?))?$"

# Busca coincidencias en la cadena de entrada
match = re.match(pattern, coltag)

# -- TODO: Raise an exception!
if match:
return match.groupdict()

def main():
"""ENTRY POINT: Install collections"""
# -- No match. Incorrect collection tag
return None


def main(coltag: str, dev: bool) -> None:
"""ENTRY POINT: Install collections
* coltag: Nombre de la coleccion + tag opcional
Ex. iceK, iceK@0.1.4
* dev: Install development version
"""

# -- Get context information
folders = commons.Folders()
collection = Collection(folders)

# -- Install the collection iceK-0.1.4
install(collection, "iceK", "0.1.4")
install(collection, "iceK")
install(collection, "iceK", "0.1.3")
install(collection, "iceWires")
install(collection, "iceIO")
install(collection, "iceGates", "0.3.1")
install(collection, "iceMux")
install(collection, "iceCoders")
install(collection, "iceFF")
install(collection, "iceRegs")
install(collection, "iceSRegs")
print()

# -- Install the collection!
install_main(collection, coltag, dev)

# -- Test
# -- TODO: Move it to a test python file
# install_main(collection, "iceK@0.1.4", True)
# install_main(collection, "iceK", True)
# install_main(collection, "iceK@0.1.3")
# install_main(collection, "iceK")
# install_main(collection, "iceWires")
# install_main(collection, "iceIO")
# install_main(collection, "iceGates")
# install_main(collection, "iceMux")
# install_main(collection, "iceCoders")
# install_main(collection, "iceFF")
# install_main(collection, "iceRegs")
# install_main(collection, "iceSRegs")


def install_main(
collection: Collection, coltag: str, dev: bool = False
) -> None:
"""Main function for installing collections
* collection: Collection class (context)
* coltag: name + version tag (Ex. iceK@0.1.4)
* dev: Development flag
* True: Install latest version from the repo
* False: Install a stable version
Main use cases:
1. If dev flag active: highest priority. Install dev collection
(the version is ignored, if given)
2. "name@version" is given --> Install the given version of collection
3. "name" is given --> Install the latest stable version
"""

# -- Parse the collection + tag
coltag = collection.parse_coltag(coltag)

if not coltag:
print("---> coleccion incorrecta!")
sys.exit(1)

# -- Get the collection name and version:
name, version = (coltag["name"], coltag["version"])

# -- Analyze all the cases
# -- The --dev flag has the highest priority. If it is set,
# -- it does not matter which version was specified (if any)
if dev:

# -- Conflict! Both version and --dev are specified
# -- --dev has the highest priority. Warn the user
if version:
click.secho(
f"Warning! Installing dev version instead of {version}",
fg="red",
)

# -- Case 1: Install development version
install(collection, name)
return

# -- Case 2: collection name + version given
if version:
install(collection, name, version)
return

# -- Case 3: Only collection name given

# Calculate the url for the collection package.json file
url = collection.package_url(name)

# -- Download the package.json
package = collection.download_package(url)

# -- Get the latest version
if package:
version = package["version"]

# -- Install the collection!
install(collection, name, version)
else:
click.secho(f"Collection: {name}", fg="red")
click.secho("No package.json downloaded", fg="red")
click.secho(f"URL: {url}", fg="red")


def install(collection: Collection, name: str, version="") -> None:
Expand All @@ -193,7 +328,6 @@ def install(collection: Collection, name: str, version="") -> None:

# -- Get the name+tag
nametag = collection.nametag(name, version)
print()
click.secho(f"Installing collection {nametag}", fg="yellow")

abs_filename = collection.abs_filename(version)
Expand Down

0 comments on commit 6c43a9d

Please sign in to comment.