diff --git a/config.ini b/config.ini index df35adb..3738e43 100644 --- a/config.ini +++ b/config.ini @@ -13,6 +13,7 @@ files: cargo-config.toml > .cargo/config.toml + [home posix] when: not host.is_windows @@ -24,12 +25,14 @@ files: nvim/init.vim > .config/nvim/init.vim + [home wsl] when: host.is_wsl files: scripts/winmode > bin/winmode + [link-files AppData] when: host.is_windows @@ -43,4 +46,11 @@ files: .vim/ftplugin > nvim/ftplugin packer.nvim > nvim-data/site/pack/packer/start/packer.nvim -# [cargo:gitui] + +[cargo-install] +crates: + just + cargo-watch + cargo-edit + cargo-get + diff --git a/prefs/cargo.py b/prefs/cargo.py new file mode 100644 index 0000000..9295c48 --- /dev/null +++ b/prefs/cargo.py @@ -0,0 +1,49 @@ +import subprocess +import shutil +import re + +class CargoInstall: + resource_name = 'cargo-install' + + def __init__(self, label, section): + self.label = label or None + self.parse_crates(section.get('crates', '')) + + def run(self): + if shutil.which('cargo') is None: + print(f"skip [cargo-install {self.label}]: cargo not found") + + if missing := self.crates - self.installed: + print(f"installing missing cargo binaries: {missing}") + cmd = ["cargo", "install"] + cmd.extend(list(missing)) + with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc: + print(proc.stdout.read()) + + def parse_crates(self, text): + self.crates = set() + for line in text.splitlines(): + if not line: + continue + crate = line.strip() + self.crates.add(crate) + + @property + def installed(self): + cmd = ["cargo", "install", "--list"] + found = set() + p = subprocess.run(cmd, capture_output=True, check=True) + for line in p.stdout.splitlines(): + if not line: + # line is empty + continue + line = line.decode("utf-8") + if re.match(r'^\s', line): + # line starts with whitespace + continue + try: + item = line.split()[0] + found.add(item) + except IndexError: + continue + return found diff --git a/prefs/host.py b/prefs/host.py index 362fa4b..e685fdb 100644 --- a/prefs/host.py +++ b/prefs/host.py @@ -8,6 +8,7 @@ import os import platform import sys import pathlib +import shutil from functools import cached_property class Host: @@ -61,4 +62,10 @@ class Host: """ return pathlib.Path.home() + def has(self, cmd): + """ + whether or not the machine has the specified command + """ + return shutil.which(cmd) is not None + sys.modules[__name__] = Host() diff --git a/prefs/log.py b/prefs/log.py index 06354d5..7db668b 100644 --- a/prefs/log.py +++ b/prefs/log.py @@ -5,7 +5,7 @@ a logging object import logging import sys -class _Log: +class Log: def __init__(self): logging.basicConfig(level=logging.INFO, format='') self._target = logging.getLogger() @@ -16,4 +16,4 @@ class _Log: def __dir__(self): return dir(self._target) -sys.modules[__name__] = _Log() +sys.modules[__name__] = Log() diff --git a/prefs/resource.py b/prefs/resource.py index d932f16..2451ef9 100644 --- a/prefs/resource.py +++ b/prefs/resource.py @@ -1,8 +1,9 @@ from .home import Home from .linker import LinkFiles +from .cargo import CargoInstall class Resource: - resource_types = [Home, LinkFiles] + resource_types = [Home, LinkFiles, CargoInstall] @classmethod def from_name(cls, name):