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

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""" 

9 

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) 

28 

29 

30# ----------- apio clean 

31 

32 

33def _delete_candidates(candidates: List[str]): 

34 """Delete given files and dirs.""" 

35 

36 # pylint: disable=broad-exception-caught 

37 

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}") 

41 

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 

51 

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 

59 

60 # -- Handle deletion exceptions, e.g. permissions issues. 

61 except Exception as e: 

62 cout(f"{e}", style=ERROR) 

63 sys.exit(1) 

64 

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) 

70 

71 # -- Report item deletion. 

72 if item_deleted: 

73 items_deleted = True 

74 cout(f"- Removed {path}") 

75 

76 # -- Print a summary. 

77 if items_deleted: 

78 cout("Cleanup completed", style=SUCCESS) 

79 else: 

80 cout("Already clean", style=SUCCESS) 

81 

82 

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. 

87 

88Example:[code] 

89 apio clean[/code] 

90""" 

91 

92 

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 """ 

107 

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 ) 

118 

119 # -- Change to the project's folder. 

120 os.chdir(apio_ctx.project_dir) 

121 

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") 

132 

133 # -- Clean the root build directory. 

134 candidates.append(PROJECT_BUILD_PATH) 

135 

136 # -- Clean and report. 

137 _delete_candidates(candidates) 

138 

139 sys.exit(0)