From e7b2bb4828a535664b267eaa312c7fb3531dd021 Mon Sep 17 00:00:00 2001 From: setop Date: Sat, 11 Mar 2023 00:15:06 +0100 Subject: [PATCH] almost working impl --- TODO.md | 8 ++++++++ catalog.yaml | 53 +++++++++++++++++++++++++++++++++++++++--------- cliget.py | 38 ++++++++++++++++++++++++++-------- requirements.txt | 4 ++-- validate.py | 27 ++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 21 deletions(-) create mode 100644 validate.py diff --git a/TODO.md b/TODO.md index 727bad9..6eaf90e 100644 --- a/TODO.md +++ b/TODO.md @@ -9,6 +9,13 @@ - [*] code style => blake, defaults - [ ] tests + - [ ] catalog completion report: + - has github repo + - has release + - has semver release + - output semver on `--version` + - has linux + x86_64 + tgz asset + - has exe at a known place - [ ] cli x (not there, there with old version, there with latest version) - [ ] choose forge(s), one will be the golden source of the catalog @@ -46,3 +53,4 @@ - [ ] async loading of versions ; fill output when available - [ ] cache GH response for a given time - [ ] explore a way to combine docopt and baker + - [ ] look at fig completions diff --git a/catalog.yaml b/catalog.yaml index 8bf82a9..33f873a 100644 --- a/catalog.yaml +++ b/catalog.yaml @@ -1,5 +1,5 @@ ab: - name: Apache Benchmark + fullname: Apache Benchmark desc: a tool for benchmarking your Apache Hypertext Transfer Protocol (HTTP) server arc: @@ -36,7 +36,13 @@ claws: cliget: desc: install various tools in your user profile - github: setop/cliget + #github: setop/cliget + +d2: + fullname: Declarative Diagramming + desc: a diagram scripting language that turns text to diagrams + website: https://d2-lang.com/ + github: terrastruct/d2 dslcad: desc: a programming language & interpreter for building 3D models @@ -66,8 +72,9 @@ fzf: glances: desc: a better top/htop -gloss: +glow: desc: markdown viewer + github: charmbracelet/glow gotty: desc: Share your terminal as a web application @@ -104,7 +111,7 @@ httpx: tags: curl hx: - name: helix + fullname: helix desc: text editor, inspired by vim jless: @@ -124,6 +131,18 @@ just: github: casey/just tags: task runner, rust +k3d: + desc: a lightweight wrapper to run k3s (Rancher Lab’s minimal Kubernetes distribution) in docker. + website: https://k3d.io/ + github: k3d-io/k3d + status: not a tar.gz + +k3s: + desc: Lightweight Kubernetes + website: https://k3s.io/ + github: k3s-io/k3s + status: no linux asset + ko: desc: a simple, fast container image builder for Go applications. github: ko-build/ko @@ -132,6 +151,11 @@ lazygit: desc: simple terminal UI for git commands github: jesseduffield/lazygit +litestream: + desc: Streaming replication for SQLite. + github: benbjohnson/litestream + website: https://litestream.io/ + mc: desc: minio client versions: # see https://github.com/penpyt/asdf-mc/raw/master/bin/list-all @@ -148,6 +172,11 @@ mosh: website: https://mosh.org/ github: mobile-shell/mosho +ndcu: + desc: a disk usage analyzer with an ncurses interface + website: https://dev.yorhel.nl/ncdu + releases: https://dev.yorhel.nl/download/ + outrun: desc: Delegate execution of a local command to a remote machine. github: Overv/outrun @@ -168,7 +197,7 @@ pylufic: qjs: desc: a small and embeddable Javascript engine. - name: QuiskJS + fullname: QuiskJS releases: http://ffmpeg.org/releases/ @@ -185,7 +214,7 @@ rlwrap: github: hanslub42/rlwrap rg: - name: ripgrep + fullname: ripgrep desc: improved grep github: BurntSushi/ripgrep @@ -228,6 +257,10 @@ terminews: desc: RSS client in the terminal github: antavelos/terminews +termdbms: + desc: A TUI for viewing and editing database files, CSV and SQLite. + github: mathaou/termdbms + #tldr: # desc: Collaborative cheatsheets for console commands ; must choose a client # website: https://tldr.sh/ @@ -250,7 +283,7 @@ ttyd: up: desc: interactively edit pipe - name: Ultimate Plumber + fullname: Ultimate Plumber github: akavel/up ups: @@ -259,7 +292,7 @@ ups: tag: language:go vd: - name: VisiData + fullname: VisiData desc: interactive multitool for tabular data pip: visidata,lxml,odfpy,openpyxl,pyarrow,urllib3,requests,pyinstaller @@ -284,7 +317,7 @@ wrk: github: wg/wrk ww: - name: webwormhole + fullname: webwormhole desc: creates ephemeral pipes between computers website: https://webwormhole.io/ @@ -301,7 +334,7 @@ zee: cargo: z: - name: zoxide + fullname: zoxide desc: A smarter cd command. Supports all major shells, inspired by z and autojump. github: ajeetdsouza/zoxide diff --git a/cliget.py b/cliget.py index ce7e0a2..20a3df2 100644 --- a/cliget.py +++ b/cliget.py @@ -27,6 +27,7 @@ Options: """ import logging +from collections import namedtuple import sys, os, shutil from docopt import docopt from yaml import load, SafeLoader @@ -37,6 +38,15 @@ from fuzzywuzzy import fuzz import requests +class DotDict(dict): + def __getattr__(self, name): + return self[name] if name in self else None + + +Tool = namedtuple('Tool','cli,props,lver,rver') +Tool.__annotations__ = {'cli':str, 'props':DotDict, 'lver':VersionInfo,'rver':VersionInfo} + + def trace(*mess): if "TRACE" in os.environ: print("TRACE", mess) @@ -50,11 +60,6 @@ def warn(*mess): print("WARNING:", *mess) -class DotDict(dict): - def __getattr__(self, name): - return self[name] if name in self else None - - def _load_catalog(options) -> dict: catalog = options.get( "__catalog", "https://codeberg.org/setop/cliget/raw/branch/main/catalog.yaml" @@ -70,6 +75,7 @@ def _load_catalog(options) -> dict: def _find_semver(s: str) -> VersionInfo: + trace(s) ver = VersionInfo(0, 0, 0) try: ver = VersionInfo.parse(s) @@ -164,14 +170,19 @@ def dolistupdate(options): def _gh_versions(repo: str) -> [VersionInfo | None]: [owner, repo] = repo.split("/") url = f"https://api.github.com/repos/{owner}/{repo}/releases" + # GH API raise 403 when too many requests are sent + # TODO implement retry with threshold response = requests.get(url) + trace(response) return [_find_semver(o.get("tag_name")) for o in response.json()] def _gh_version(repo: str) -> [VersionInfo | None]: [owner, repo] = repo.split("/") url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest" + trace(url) response = requests.get(url) + trace(response) return _find_semver(response.json().get("tag_name")) @@ -226,11 +237,15 @@ def doinstall(options): def _match_arch_machine(name: str) -> bool: sysname = os.uname().sysname.lower() # os machine = os.uname().machine.lower() # arch - return name.lower().find(sysname) > 0 and name.lower().find(machine) > 0 + # we don't consider libc - glic or musl - as musl is usually statically embed + lname = name.lower() + return (lname.find(sysname) > 0 + and (lname.find(machine) > 0 + or (machine == "x86_64" and lname.find("amd64") > 0)) # x86_64 and "amd64" are synonym + ) - -def _perform_gh_install(cli, repo, version=None): - # get asset list +def _get_gh_matching_release(repo): + # get asset list from last release url = f"https://api.github.com/repos/{repo}/releases/latest" r = requests.get(url) assets = r.json()["assets"] @@ -238,6 +253,10 @@ def _perform_gh_install(cli, repo, version=None): # select right asset asset = DotDict(next(filter(lambda x: _match_arch_machine(x["name"]), assets))) trace(asset.name, asset.url) + return asset + +def _perform_gh_install(cli, repo, version=None): + asset = _get_gh_matching_release(repo) # mkdirs p = os.path home = os.environ["HOME"] @@ -259,6 +278,7 @@ def _perform_gh_install(cli, repo, version=None): trace("process tgz") os.makedirs(progloc, exist_ok=True) run(["tar", "xfz", location, "-C", progloc]) + # TODO look for exe : ./cli, .//cli, exe propertie # symlink # TODO remove existing symlink os.symlink(p.join('../programs', cli, cli), p.join(home, ".local/bin", cli)) diff --git a/requirements.txt b/requirements.txt index 76c0cba..6bebde2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ pyyaml docopt semver -#fuzzywuzzy -thefuzz +fuzzywuzzy +#thefuzz #python-Levenshtein requests #tabulate diff --git a/validate.py b/validate.py new file mode 100644 index 0000000..b670e50 --- /dev/null +++ b/validate.py @@ -0,0 +1,27 @@ +from collections import namedtuple as nt +from cliget import _load_catalog as ldc, _local_version as lv, _gh_version +from semver import VersionInfo + +Result = nt('res', "cli lver gh rver asset exe") +#Result.__repr__ = lambda x: f'{x.gh}' + +# catalog completion report: +ctl = ldc({'__catalog':'catalog.yaml'}) + + +if __name__ == '__main__': + report = {} + for cli, props in ctl.items(): + lver, gh, rver, asset, exe = (False,)*5 # it is False until it is True + # output semver on `--version` + lver = lv(cli) > VersionInfo(0) + # has github repo + gh = props.github is not None + if gh: + # has semver release + rver = _gh_version(props.github) > VersionInfo(0) + # has linux + x86_64 + tgz asset + # has exe at a known place + r = Result(cli, lver, gh, rver, asset, exe) + print(r) +