diff --git a/swh/scanner/cli.py b/swh/scanner/cli.py index 74805b2..93a27c0 100644 --- a/swh/scanner/cli.py +++ b/swh/scanner/cli.py @@ -1,113 +1,127 @@ # Copyright (C) 2020 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information # WARNING: do not import unnecessary things here to keep cli startup time under # control import os from typing import Any, Dict, Optional import click +import yaml from swh.core import config from swh.core.cli import CONTEXT_SETTINGS from swh.core.cli import swh as swh_cli_group # All generic config code should reside in swh.core.config -DEFAULT_CONFIG_PATH = os.environ.get( - "SWH_CONFIG_FILE", os.path.join(click.get_app_dir("swh"), "global.yml") -) - +CONFIG_ENVVAR = "SWH_CONFIG_FILE" +DEFAULT_CONFIG_PATH = os.path.join(click.get_app_dir("swh"), "global.yml") +DEFAULT_PATH = os.environ.get(CONFIG_ENVVAR, DEFAULT_CONFIG_PATH) DEFAULT_CONFIG: Dict[str, Any] = { "web-api": { "url": "https://archive.softwareheritage.org/api/1/", "auth-token": None, } } -@swh_cli_group.group(name="scanner", context_settings=CONTEXT_SETTINGS) +CONFIG_FILE_HELP = f"""Configuration file: + +\b +The CLI option or the environment variable will fail if invalid. +CLI option is checked first. +Then, environment variable {CONFIG_ENVVAR} is checked. +Then, if cannot load the default path, a set of default values are used. +Default config path is {DEFAULT_CONFIG_PATH}. +Default config values are: + +\b +{yaml.dump(DEFAULT_CONFIG)}""" +SCANNER_HELP = f"""Software Heritage Scanner tools. + +{CONFIG_FILE_HELP}""" + + +@swh_cli_group.group( + name="scanner", context_settings=CONTEXT_SETTINGS, help=SCANNER_HELP, +) @click.option( "-C", "--config-file", default=None, type=click.Path(exists=False, dir_okay=False, path_type=str), - help=f"""YAML configuration file. If absent and cannot load the default one, - default parameters are used. - Default config path is {DEFAULT_CONFIG_PATH}. - Default config values are {DEFAULT_CONFIG} - """, + help="""YAML configuration file""", ) @click.pass_context def scanner(ctx, config_file: Optional[str]): - """Software Heritage Scanner tools.""" - if config_file is None and config.config_exists(DEFAULT_CONFIG_PATH): - config_file = DEFAULT_CONFIG_PATH + if config_file is None and config.config_exists(DEFAULT_PATH): + config_file = DEFAULT_PATH if config_file is None: conf = DEFAULT_CONFIG else: # read_raw_config do not fail on ENOENT if not config.config_exists(config_file): raise FileNotFoundError(config_file) conf = config.read_raw_config(config.config_basepath(config_file)) conf = config.merge_configs(DEFAULT_CONFIG, conf) ctx.ensure_object(dict) ctx.obj["config"] = conf @scanner.command(name="scan") @click.argument("root_path", required=True, type=click.Path(exists=True)) @click.option( "-u", "--api-url", default=None, metavar="API_URL", show_default=True, help="URL for the api request", ) @click.option( "--exclude", "-x", "patterns", metavar="PATTERN", multiple=True, help="Exclude directories using glob patterns \ (e.g., '*.git' to exclude all .git directories)", ) @click.option( "-f", "--output-format", "out_fmt", default="text", show_default=True, type=click.Choice(["text", "json", "ndjson", "sunburst"], case_sensitive=False), help="The output format", ) @click.option( "-i", "--interactive", is_flag=True, help="Show the result in a dashboard" ) @click.pass_context def scan(ctx, root_path, api_url, patterns, out_fmt, interactive): """Scan a source code project to discover files and directories already present in the archive""" from .scanner import scan config = ctx.obj["config"] if api_url: if not api_url.endswith("/"): api_url += "/" config["web-api"]["url"] = api_url scan(config, root_path, patterns, out_fmt, interactive) def main(): return scanner(auto_envvar_prefix="SWH_SCANNER") if __name__ == "__main__": main()