|
7 | 7 |
|
8 | 8 | import click |
9 | 9 |
|
10 | | -from dda.cli.base import dynamic_command |
| 10 | +from dda.cli.base import dynamic_command, pass_app |
| 11 | +from dda.utils.fs import Path |
11 | 12 |
|
12 | 13 | if TYPE_CHECKING: |
13 | | - from dda.utils.fs import Path |
| 14 | + from dda.cli.application import Application |
14 | 15 |
|
15 | 16 |
|
16 | 17 | @dynamic_command( |
17 | 18 | short_help="Query the list of Go build tags existing in the repository.", |
18 | 19 | ) |
19 | 20 | @click.option( |
20 | | - "repo", |
| 21 | + "--repo", |
21 | 22 | "-r", |
22 | | - type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), |
23 | | - help="The repository to use.", |
| 23 | + type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True, path_type=Path), |
| 24 | + default=Path.cwd(), |
| 25 | + # NOTE: Should we default to the root of the currently-open git repository? |
| 26 | + help="The repository path to use. Defaults to the current working directory.", |
24 | 27 | ) |
25 | 28 | @click.option("--json", "-j", is_flag=True, help="Format the output as JSON.") |
26 | | -def cmd(repo: Path, *, json: bool) -> None: |
27 | | - pass |
| 29 | +@click.option("--map", "-m", is_flag=True, help="Map the tags to the paths where they are used.") |
| 30 | +@click.option( |
| 31 | + "--exclude", |
| 32 | + "-e", |
| 33 | + multiple=True, |
| 34 | + help="Exclude files or directories from the search using a regular expression. Can be specified multiple times.", |
| 35 | +) |
| 36 | +@pass_app |
| 37 | +def cmd(app: Application, *, repo: Path, json: bool, map: bool, exclude: list[str]) -> None: # noqa: A002 |
| 38 | + import re |
| 39 | + |
| 40 | + from dda.build.go.tags.search import search_build_tags |
| 41 | + |
| 42 | + result_raw = search_build_tags(repo, exclude_patterns=[re.compile(pattern) for pattern in exclude]) |
| 43 | + |
| 44 | + # Need to convert the set[Path] to a list[str] to be able to serialize to JSON |
| 45 | + # Sort the inner list elements alphabetically for consistent output |
| 46 | + result_map = {tag: sorted(str(path) for path in paths) for tag, paths in result_raw.items()} |
| 47 | + result_list = sorted(result_map.keys(), key=lambda x: len(result_map[x]), reverse=True) |
| 48 | + |
| 49 | + if json: |
| 50 | + from json import dumps |
| 51 | + |
| 52 | + result = result_map if map else result_list |
| 53 | + app.output(dumps(result)) |
| 54 | + return |
| 55 | + |
| 56 | + # If outputting for humans, display the tags in a table |
| 57 | + # This table is sorted by the most frequently used tags first |
| 58 | + if len(result_list) == 0: |
| 59 | + app.display("No build tags found.") |
| 60 | + return |
| 61 | + |
| 62 | + if not map: |
| 63 | + app.display("\n".join(result_list)) |
| 64 | + return |
| 65 | + |
| 66 | + from collections import OrderedDict |
| 67 | + |
| 68 | + # Order the tags by most-used first (by "count"), descending |
| 69 | + result_human = OrderedDict([ |
| 70 | + (tag, {"count": len(result_map[tag]), "paths": ", ".join(result_map[tag])}) for tag in result_list |
| 71 | + ]) |
| 72 | + app.display_table(result_human) |
| 73 | + return |
0 commit comments