changeset 472:97412ea9b3fa

Improve install script, add scoop apps on Windows.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 28 Jul 2019 22:26:24 -0700
parents 31079b060068
children e368c8ae2a4b
files install.cfg install.py
diffstat 2 files changed, 80 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/install.cfg	Tue Apr 09 19:09:04 2019 -0700
+++ b/install.cfg	Sun Jul 28 22:26:24 2019 -0700
@@ -55,6 +55,21 @@
 yankring = [git]https://github.com/vim-scripts/YankRing.vim.git
 
 
+[wintools]
+7zip =
+consolez =
+fd = 
+fzf =
+git =
+mercurial = 32bit
+openssh =
+putty =
+ripgrep =
+sysinternals =
+universal-ctags =
+vim =
+
+
 [mactools]
 asciinema = 
 ccat = 
--- a/install.py	Tue Apr 09 19:09:04 2019 -0700
+++ b/install.py	Sun Jul 28 22:26:24 2019 -0700
@@ -9,6 +9,8 @@
 import configparser
 
 
+# Utility stuff.
+
 dotfiles_dir = os.path.abspath(os.path.dirname(__file__))
 
 is_nix = True
@@ -63,7 +65,10 @@
         os.remove(link_full_path)
 
     print("%s -> %s" % (link_full_path, orig_full_path))
-    os.symlink(orig_full_path, link_full_path)
+    if not is_windows or os.path.isfile(orig_full_path):
+        os.symlink(orig_full_path, link_full_path)
+    else:
+        subprocess.check_call(['mklink', '/J', link_full_path, orig_full_path], shell=True)
     if mode is not None:
         os.chmod(link_full_path, mode)
 
@@ -86,6 +91,8 @@
     shutil.rmtree(dirpath, onerror=_on_rmtree_err)
 
 
+# Installer method decorators.
+
 def only_on_nix(f):
     @functools.wraps(f)
     def decorator(*args, **kwargs):
@@ -127,6 +134,8 @@
     return wrapper
 
 
+# Installer methods.
+
 @only_on_nix
 def install_bash():
     mklink('bashrc/bashrc', '.bashrc')
@@ -388,6 +397,41 @@
         subprocess.check_call(args)
 
 
+@only_on_win
+@run_priority(209)
+def install_scoop():
+    if shutil.which('scoop') is None:
+        print("Installing Scoop")
+        subprocess.check_call(
+            '@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" '
+            '-NoProfile -InputFormat None -ExecutionPolicy Bypass '
+            '-Command "iex (new-object net.webclient).downloadstring(\'https://get.scoop.sh\')"')
+        subprocess.check_call(
+            ['scoop.cmd', 'bucket', 'add', 'extras'])
+    else:
+        print("Scoop is already installed")
+
+@only_on_win
+@needs_config
+@supports_forcing
+@run_priority(208)
+def install_wintools(cfg, force=False):
+    if not cfg.has_section('wintools'):
+        return
+        
+    for name, arch in cfg.items('wintools'):
+        args = ['scoop.cmd', 'install', name]
+        if arch:
+            args += ['-a', arch]
+        subprocess.check_call(args)
+
+
+# Main stuff!
+
+class FatalInstallerError(Exception):
+	pass
+	
+
 def main():
     print("dotfiles installer")
     print("python %s" % sys.version)
@@ -423,12 +467,23 @@
     parser = argparse.ArgumentParser()
     parser.add_argument(
         'module', nargs='*',
-        choices=mod_names,
         help="Which module(s) to install. Defaults to all modules.")
     parser.add_argument(
+        '-l', '--list', action='store_true',
+        help="List available modules to install.")
+    parser.add_argument(
         '-f', '--force', action='store_true',
         help="Force installation by overwriting things.")
     args = parser.parse_args()
+    
+    # Print list and exit if needed.
+    if args.list:
+        print("Available modules to install:")
+        for nm in mod_names:
+            print(nm)
+        print()
+        print("Specify 'all' to install all modules.")
+        return
 
     # Get the list of methods to run.
     funcs = []
@@ -436,6 +491,8 @@
     if 'all' in selected_mods:
         selected_mods = set(mod_names)
         selected_mods.remove('all')
+    selected_mods.difference_update([neg[3:] for neg in args.module if neg.startswith('no-')])
+    
     for mn in selected_mods:
         func = getattr(this_mod, 'install_%s' % mn)
         funcs.append((mn, func))
@@ -461,9 +518,13 @@
         try:
             func(*f_args, **f_kwargs)
         except Exception as ex:
+            failed_installs.append(name)
             print("ERROR: %s" % ex)
-            print("Skipping install of '%s'." % name)
-            failed_installs.append(name)
+            if isinstance(ex, FatalInstallerError):
+                print("Aborting all remaining installs because '%s' failed!" % name)
+                break
+            else:
+                print("Skipping install of '%s'." % name)
     if failed_installs:
         for name in failed_installs:
             print("ERROR: failed to install '%s'." % name)