|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
| 15 | +import fnmatch |
15 | 16 | import os
|
16 | 17 | import contextlib
|
17 | 18 | import json
|
18 |
| -import requests |
19 | 19 | import subprocess
|
20 | 20 | import sys
|
21 | 21 | import shutil
|
@@ -107,6 +107,20 @@ def safe_remove_directory(path: str) -> bool:
|
107 | 107 | return True
|
108 | 108 |
|
109 | 109 |
|
| 110 | +@safe_file_operation |
| 111 | +def safe_remove_directory_pattern(base_path: str, pattern: str) -> bool: |
| 112 | + """Safely remove directories matching a pattern with error handling.""" |
| 113 | + if not os.path.exists(base_path): |
| 114 | + return True |
| 115 | + # Find all directories matching the pattern in the base directory |
| 116 | + for item in os.listdir(base_path): |
| 117 | + item_path = os.path.join(base_path, item) |
| 118 | + if os.path.isdir(item_path) and fnmatch.fnmatch(item, pattern): |
| 119 | + shutil.rmtree(item_path) |
| 120 | + logger.debug(f"Directory removed: {item_path}") |
| 121 | + return True |
| 122 | + |
| 123 | + |
110 | 124 | @safe_file_operation
|
111 | 125 | def safe_copy_file(src: str, dst: str) -> bool:
|
112 | 126 | """Safely copy files with error handling."""
|
@@ -138,6 +152,17 @@ def _get_tool_paths(self, tool_name: str) -> Dict[str, str]:
|
138 | 152 | """Get centralized path calculation for tools with caching."""
|
139 | 153 | if tool_name not in self._tools_cache:
|
140 | 154 | tool_path = os.path.join(self.packages_dir, tool_name)
|
| 155 | + # Remove all directories containing '@' in their name |
| 156 | + try: |
| 157 | + for item in os.listdir(self.packages_dir): |
| 158 | + if '@' in item and item.startswith(tool_name): |
| 159 | + item_path = os.path.join(self.packages_dir, item) |
| 160 | + if os.path.isdir(item_path): |
| 161 | + safe_remove_directory(item_path) |
| 162 | + logger.debug(f"Removed directory with '@' in name: {item_path}") |
| 163 | + except OSError as e: |
| 164 | + logger.error(f"Error scanning packages directory for '@' directories: {e}") |
| 165 | + |
141 | 166 | self._tools_cache[tool_name] = {
|
142 | 167 | 'tool_path': tool_path,
|
143 | 168 | 'package_path': os.path.join(tool_path, "package.json"),
|
@@ -287,9 +312,19 @@ def _handle_existing_tool(
|
287 | 312 | logger.debug(f"Tool {tool_name} found with correct version")
|
288 | 313 | return True
|
289 | 314 |
|
290 |
| - # Wrong version, reinstall |
| 315 | + # Wrong version, reinstall - remove similar paths too |
291 | 316 | logger.info(f"Reinstalling {tool_name} due to version mismatch")
|
| 317 | + |
| 318 | + tool_base_name = os.path.basename(paths['tool_path']) |
| 319 | + packages_dir = os.path.dirname(paths['tool_path']) |
| 320 | + |
| 321 | + # Remove similar directories with version suffixes FIRST (e.g., xtensa@src, xtensa.12232) |
| 322 | + safe_remove_directory_pattern(packages_dir, f"{tool_base_name}@*") |
| 323 | + safe_remove_directory_pattern(packages_dir, f"{tool_base_name}.*") |
| 324 | + |
| 325 | + # Then remove the main tool directory (if it still exists) |
292 | 326 | safe_remove_directory(paths['tool_path'])
|
| 327 | + |
293 | 328 | return self.install_tool(tool_name, retry_count + 1)
|
294 | 329 |
|
295 | 330 | def _configure_arduino_framework(self, frameworks: List[str]) -> None:
|
|
0 commit comments