| 332 | |
| 333 | |
| 334 | class ListCompositionsCommand(Command): |
| 335 | name = "list-compositions" |
| 336 | help = "list the directories that contain compositions and their summaries" |
| 337 | |
| 338 | def run(self, args: argparse.Namespace) -> None: |
| 339 | import multiprocessing |
| 340 | |
| 341 | repo = mzbuild.Repository.from_arguments(MZ_ROOT, args) |
| 342 | items = sorted(repo.compositions.items(), key=lambda item: item[1]) |
| 343 | |
| 344 | ctx = multiprocessing.get_context("fork") |
| 345 | with ctx.Pool( |
| 346 | processes=os.cpu_count(), |
| 347 | initializer=_init_list_worker, |
| 348 | initargs=(repo.rd, repo.compositions), |
| 349 | ) as pool: |
| 350 | descriptions = pool.map( |
| 351 | _load_composition_description, [name for name, _ in items] |
| 352 | ) |
| 353 | |
| 354 | for (name, path), description in zip(items, descriptions): |
| 355 | print(os.path.relpath(path, repo.root)) |
| 356 | if description: |
| 357 | # Emit the first paragraph of the description. |
| 358 | for line in description.split("\n"): |
| 359 | if line.strip() == "": |
| 360 | break |
| 361 | print(f" {line}") |
| 362 | |
| 363 | |
| 364 | _list_worker_repo: mzbuild.Repository | None = None |