2021-08-17 18:48:25 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
from configparser import ConfigParser
|
2021-10-17 00:21:22 +02:00
|
|
|
from os import PathLike
|
2021-08-17 18:48:25 +02:00
|
|
|
from pathlib import Path
|
2022-01-10 07:23:37 +01:00
|
|
|
from typing import Iterator, List, Optional, Set
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
DEFAULT_PACKAGES_FILENAME = "packages.ini"
|
|
|
|
FORMATS = ("list", "line")
|
2022-09-09 20:45:59 +02:00
|
|
|
DISTRIBUTIONS = ("focal", "bullseye", "jammy", "bookworm")
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
SETTINGS_SECTION = "=settings"
|
|
|
|
DEVELOPMENT_SECTION = "=development"
|
|
|
|
|
|
|
|
|
2021-10-17 00:21:22 +02:00
|
|
|
def load_packages(
|
|
|
|
raw: str,
|
|
|
|
distribution: str,
|
|
|
|
development: bool = False,
|
2022-01-10 07:23:37 +01:00
|
|
|
exclude: Optional[List[str]] = None,
|
2021-10-17 00:21:22 +02:00
|
|
|
) -> Set[str]:
|
|
|
|
if distribution not in DISTRIBUTIONS:
|
|
|
|
raise ValueError(f"Invalid distribution '{distribution}'")
|
|
|
|
|
2021-08-17 18:48:25 +02:00
|
|
|
manager = ConfigParser(default_section=SETTINGS_SECTION)
|
|
|
|
manager.read_string(raw)
|
|
|
|
|
|
|
|
packages = set()
|
2022-01-10 07:23:37 +01:00
|
|
|
exclude = set(exclude or [])
|
2021-08-17 18:48:25 +02:00
|
|
|
for section, entries in manager.items():
|
2022-01-10 07:23:37 +01:00
|
|
|
if not development and section == DEVELOPMENT_SECTION or section in exclude:
|
2021-08-17 18:48:25 +02:00
|
|
|
continue
|
|
|
|
|
|
|
|
for package, distributions in entries.items():
|
|
|
|
if distribution in distributions.split(", "):
|
|
|
|
packages.add(package)
|
|
|
|
|
|
|
|
return packages
|
|
|
|
|
|
|
|
|
2021-10-17 00:21:22 +02:00
|
|
|
def list_packages_files(
|
|
|
|
paths: List[PathLike],
|
|
|
|
) -> Iterator[Path]:
|
|
|
|
for path_like in paths:
|
|
|
|
path = Path(path_like)
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
if path.is_dir():
|
|
|
|
path = path / DEFAULT_PACKAGES_FILENAME
|
|
|
|
|
|
|
|
if not path.is_file():
|
2023-02-01 20:38:58 +01:00
|
|
|
raise ValueError(f"{path} is not a file!")
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
yield path
|
|
|
|
|
|
|
|
|
2021-10-17 00:21:22 +02:00
|
|
|
def list_packages(
|
|
|
|
paths: List[PathLike],
|
|
|
|
distribution: str,
|
|
|
|
development: bool = False,
|
2022-01-10 07:23:37 +01:00
|
|
|
exclude: Optional[List[str]] = None,
|
2021-10-17 00:21:22 +02:00
|
|
|
) -> Set[str]:
|
2021-08-17 18:48:25 +02:00
|
|
|
packages = set()
|
|
|
|
for package_file in list_packages_files(paths):
|
|
|
|
raw = package_file.read_text()
|
2022-01-10 07:23:37 +01:00
|
|
|
packages.update(load_packages(raw, distribution, development, exclude))
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
return set(sorted(packages))
|
|
|
|
|
|
|
|
|
|
|
|
def run():
|
|
|
|
parser = ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
|
|
"-f",
|
|
|
|
"--format",
|
|
|
|
choices=FORMATS,
|
|
|
|
help="print packages list in a specific format.",
|
|
|
|
default="list",
|
2021-09-07 23:10:21 +02:00
|
|
|
)
|
2021-08-17 18:48:25 +02:00
|
|
|
parser.add_argument(
|
|
|
|
"-d",
|
|
|
|
"--dev",
|
|
|
|
help="include development packages.",
|
|
|
|
action="store_true",
|
|
|
|
)
|
2022-01-10 07:23:37 +01:00
|
|
|
parser.add_argument(
|
|
|
|
"-e",
|
|
|
|
"--exclude",
|
|
|
|
help="exclude packages sections.",
|
2022-03-02 08:45:45 +01:00
|
|
|
action="append",
|
2022-01-10 07:23:37 +01:00
|
|
|
)
|
2021-08-17 18:48:25 +02:00
|
|
|
parser.add_argument(
|
|
|
|
"distribution",
|
2021-10-17 00:21:22 +02:00
|
|
|
choices=DISTRIBUTIONS,
|
2021-08-17 18:48:25 +02:00
|
|
|
help="list packages for the given distribution.",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"path",
|
|
|
|
nargs="+",
|
|
|
|
help="list packages from given files or directories.",
|
|
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2022-01-10 07:23:37 +01:00
|
|
|
packages = list_packages(args.path, args.distribution, args.dev, args.exclude)
|
2021-08-17 18:48:25 +02:00
|
|
|
|
|
|
|
if args.format == "list":
|
|
|
|
print("\n".join(packages))
|
|
|
|
else:
|
|
|
|
print(" ".join(packages))
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
run()
|