Coverage for apio/commands/apio_clean.py: 88%
51 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 10:20 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-06 10:20 +0000
1# -*- coding: utf-8 -*-
2# -- This file is part of the Apio project
3# -- (C) 2016-2024 FPGAwars
4# -- Authors
5# -- * Jesús Arroyo (2016-2019)
6# -- * Juan Gonzalez (obijuan) (2019-2024)
7# -- License GPLv2
8"""Implementation of 'apio clean' command"""
10import os
11import shutil
12import sys
13from glob import glob
14from typing import Optional, List
15from pathlib import Path
16import click
17from apio.commands import options
18from apio.utils import cmd_util, util
19from apio.common.apio_console import cout, cerror
20from apio.common.apio_styles import SUCCESS, ERROR
21from apio.common.common_util import PROJECT_BUILD_PATH
22from apio.apio_context import (
23 ApioContext,
24 PackagesPolicy,
25 ProjectPolicy,
26 RemoteConfigPolicy,
27)
30# ----------- apio clean
33def _delete_candidates(candidates: List[str]):
34 """Delete given files and dirs."""
36 # pylint: disable=broad-exception-caught
38 # -- Dump for debugging.
39 if util.is_debug(1): 39 ↛ 40line 39 didn't jump to line 40 because the condition on line 39 was never true
40 cout(f"\nDeletion candidates: {candidates}")
42 # -- Delete candidates that exists.
43 items_deleted = False
44 for path in candidates:
45 item_deleted = False
46 try:
47 # -- Delete a file.
48 if os.path.isfile(path):
49 os.remove(path)
50 item_deleted = True
52 # -- Delete a directory.
53 elif os.path.isdir(path):
54 # -- Sanity check to make sure we don't delete the entire
55 # -- hard drive.
56 assert "_build" in str(path), path
57 shutil.rmtree(path)
58 item_deleted = True
60 # -- Handle deletion exceptions, e.g. permissions issues.
61 except Exception as e:
62 cout(f"{e}", style=ERROR)
63 sys.exit(1)
65 # -- Check that the item was indeed deleted (e.g if it's not a file
66 # -- neither a directory).
67 if os.path.exists(path): 67 ↛ 68line 67 didn't jump to line 68 because the condition on line 67 was never true
68 cerror(f"Failed to delete '{path}'")
69 sys.exit(1)
71 # -- Report item deletion.
72 if item_deleted:
73 items_deleted = True
74 cout(f"- Removed {path}")
76 # -- Print a summary.
77 if items_deleted:
78 cout("Cleanup completed", style=SUCCESS)
79 else:
80 cout("Already clean", style=SUCCESS)
83# -- Text in the rich-text format of the python rich library.
84APIO_CLEAN_HELP = """
85The command 'apio clean' removes all the output files previously generated \
86by apio commands.
88Example:[code]
89 apio clean[/code]
90"""
93@click.command(
94 name="clean",
95 cls=cmd_util.ApioCommand,
96 short_help="Delete the apio generated files.",
97 help=APIO_CLEAN_HELP,
98)
99@options.project_dir_option
100def cli(
101 # Options
102 project_dir: Optional[Path],
103):
104 """Implements the apio clean command. It deletes temporary files generated
105 by apio commands.
106 """
108 # -- Create the apio context.
109 # -- We suppress the message with the env and board ids since it's
110 # -- not relevant for this command.
111 apio_ctx = ApioContext(
112 project_policy=ProjectPolicy.PROJECT_REQUIRED,
113 remote_config_policy=RemoteConfigPolicy.CACHED_OK,
114 packages_policy=PackagesPolicy.ENSURE_PACKAGES,
115 project_dir_arg=project_dir,
116 report_env=False,
117 )
119 # -- Change to the project's folder.
120 os.chdir(apio_ctx.project_dir)
122 # -- TODO: Remove the cleanup of legacy files after releasing the first
123 # -- release with the _build directory.
124 # --
125 # --
126 # -- Until apio 0.9.6, the build artifacts were created in the project
127 # -- directory rather than the _build directory. To simplify the
128 # -- transition we clean here also left over files from 0.9.5.
129 candidates = glob("hardware.*")
130 candidates += glob("*_tb.vcd")
131 candidates += glob("*_tb.out")
133 # -- Clean the root build directory.
134 candidates.append(PROJECT_BUILD_PATH)
136 # -- Clean and report.
137 _delete_candidates(candidates)
139 sys.exit(0)