X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/a2408b3cb23fe252b3674cee484d742496bb3411..7af3abd38392588ac737bae09f6b15d80fe344b1:/src/black_primer/cli.py?ds=inline

diff --git a/src/black_primer/cli.py b/src/black_primer/cli.py
index 09ab03f..8524b59 100644
--- a/src/black_primer/cli.py
+++ b/src/black_primer/cli.py
@@ -1,19 +1,27 @@
-#!/usr/bin/env python3
+# coding=utf8
 
 import asyncio
+import json
 import logging
 import sys
 from datetime import datetime
-from os import cpu_count
 from pathlib import Path
 from shutil import rmtree, which
 from tempfile import gettempdir
-from typing import Any, Union
+from typing import Any, List, Optional, Union
 
 import click
 
 from black_primer import lib
 
+# If our environment has uvloop installed lets use it
+try:
+    import uvloop
+
+    uvloop.install()
+except ImportError:
+    pass
+
 
 DEFAULT_CONFIG = Path(__file__).parent / "primer.json"
 _timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
@@ -22,8 +30,8 @@ LOG = logging.getLogger(__name__)
 
 
 def _handle_debug(
-    ctx: click.core.Context,
-    param: Union[click.core.Option, click.core.Parameter],
+    ctx: Optional[click.core.Context],
+    param: Optional[Union[click.core.Option, click.core.Parameter]],
     debug: Union[bool, int, str],
 ) -> Union[bool, int, str]:
     """Turn on debugging if asked otherwise INFO default"""
@@ -35,11 +43,42 @@ def _handle_debug(
     return debug
 
 
+def load_projects(config_path: Path) -> List[str]:
+    with open(config_path) as config:
+        return sorted(json.load(config)["projects"].keys())
+
+
+# Unfortunately does import time file IO - but appears to be the only
+# way to get `black-primer --help` to show projects list
+DEFAULT_PROJECTS = load_projects(DEFAULT_CONFIG)
+
+
+def _projects_callback(
+    ctx: click.core.Context,
+    param: Optional[Union[click.core.Option, click.core.Parameter]],
+    projects: str,
+) -> List[str]:
+    requested_projects = set(projects.split(","))
+    available_projects = set(
+        DEFAULT_PROJECTS
+        if str(DEFAULT_CONFIG) == ctx.params["config"]
+        else load_projects(ctx.params["config"])
+    )
+
+    unavailable = requested_projects - available_projects
+    if unavailable:
+        LOG.error(f"Projects not found: {unavailable}. Available: {available_projects}")
+
+    return sorted(requested_projects & available_projects)
+
+
 async def async_main(
     config: str,
     debug: bool,
     keep: bool,
     long_checkouts: bool,
+    no_diff: bool,
+    projects: List[str],
     rebase: bool,
     workdir: str,
     workers: int,
@@ -55,15 +94,21 @@ async def async_main(
 
     try:
         ret_val = await lib.process_queue(
-            config, work_path, workers, keep, long_checkouts, rebase
+            config,
+            work_path,
+            workers,
+            projects,
+            keep,
+            long_checkouts,
+            rebase,
+            no_diff,
         )
         return int(ret_val)
+
     finally:
         if not keep and work_path.exists():
             LOG.debug(f"Removing {work_path}")
-            rmtree(work_path)
-
-    return -2
+            rmtree(work_path, onerror=lib.handle_PermissionError)
 
 
 @click.command(context_settings={"help_option_names": ["-h", "--help"]})
@@ -74,6 +119,8 @@ async def async_main(
     type=click.Path(exists=True),
     show_default=True,
     help="JSON config file path",
+    # Eager - because config path is used by other callback options
+    is_eager=True,
 )
 @click.option(
     "--debug",
@@ -96,6 +143,19 @@ async def async_main(
     show_default=True,
     help="Pull big projects to test",
 )
+@click.option(
+    "--no-diff",
+    is_flag=True,
+    show_default=True,
+    help="Disable showing source file changes in black output",
+)
+@click.option(
+    "--projects",
+    default=",".join(DEFAULT_PROJECTS),
+    callback=_projects_callback,
+    show_default=True,
+    help="Comma separated list of projects to run",
+)
 @click.option(
     "-R",
     "--rebase",
@@ -114,7 +174,7 @@ async def async_main(
 @click.option(
     "-W",
     "--workers",
-    default=int((cpu_count() or 4) / 2) or 1,
+    default=2,
     type=int,
     show_default=True,
     help="Number of parallel worker coroutines",