@@ -273,7 +273,7 @@ def _extract_version_from_url(self, version_string: str) -> str:
273273 def _install_tl_install (self , version : str ) -> bool :
274274 """
275275 Install tool-esp_install ONLY when necessary
276- and handles backwards compability for tl-install.
276+ and handles backwards compatibility for tl-install.
277277
278278 Args:
279279 version: Version string or URL to install
@@ -298,15 +298,15 @@ def _install_tl_install(self, version: str) -> bool:
298298 self .packages [tl_install_name ]["optional" ] = False
299299 self .packages [tl_install_name ]["version" ] = version
300300 pm .install (version )
301- # Ensure backward compability by removing pio install status indicator
301+ # Ensure backward compatibility by removing pio install status indicator
302302 tl_piopm_path = os .path .join (tl_install_path , ".piopm" )
303303 safe_remove_file (tl_piopm_path )
304304
305305 if os .path .exists (os .path .join (tl_install_path , "package.json" )):
306306 logger .info (f"{ tl_install_name } successfully installed and verified" )
307307 self .packages [tl_install_name ]["optional" ] = True
308308
309- # Handle old tl-install to keep backwards compability
309+ # Handle old tl-install to keep backwards compatibility
310310 if old_tl_install_exists :
311311 # Copy tool-esp_install content to tl-install location
312312 if safe_copy_directory (tl_install_path , old_tl_install_path ):
@@ -322,23 +322,39 @@ def _install_tl_install(self, version: str) -> bool:
322322 logger .error (f"Error installing { tl_install_name } : { e } " )
323323 return False
324324
325+ def _cleanup_versioned_tool_directories (self , tool_name : str ) -> None :
326+ """
327+ Clean up versioned tool directories containing '@' or version suffixes.
328+ This function should be called during every tool version check.
329+
330+ Args:
331+ tool_name: Name of the tool to clean up
332+ """
333+ if not os .path .exists (self .packages_dir ) or not os .path .isdir (self .packages_dir ):
334+ return
335+
336+ try :
337+ # Remove directories with '@' in their name (e.g., tool-name@version, tool-name@src)
338+ safe_remove_directory_pattern (self .packages_dir , f"{ tool_name } @*" )
339+
340+ # Remove directories with version suffixes (e.g., tool-name.12345)
341+ safe_remove_directory_pattern (self .packages_dir , f"{ tool_name } .*" )
342+
343+ # Also check for any directory that starts with tool_name and contains '@'
344+ for item in os .listdir (self .packages_dir ):
345+ if item .startswith (tool_name ) and '@' in item :
346+ item_path = os .path .join (self .packages_dir , item )
347+ if os .path .isdir (item_path ):
348+ safe_remove_directory (item_path )
349+ logger .debug (f"Removed versioned directory: { item_path } " )
350+
351+ except OSError as e :
352+ logger .error (f"Error cleaning up versioned directories for { tool_name } : { e } " )
325353
326354 def _get_tool_paths (self , tool_name : str ) -> Dict [str , str ]:
327355 """Get centralized path calculation for tools with caching."""
328356 if tool_name not in self ._tools_cache :
329357 tool_path = os .path .join (self .packages_dir , tool_name )
330- # Remove all directories containing '@' in their name
331- try :
332- if os .path .exists (self .packages_dir ) and os .path .isdir (self .packages_dir ):
333- for item in os .listdir (self .packages_dir ):
334- if '@' in item and item .startswith (tool_name ):
335- item_path = os .path .join (self .packages_dir , item )
336- if os .path .isdir (item_path ):
337- safe_remove_directory (item_path )
338- logger .debug (f"Removed directory with '@' in name: { item_path } " )
339-
340- except OSError as e :
341- logger .error (f"Error scanning packages directory for '@' directories: { e } " )
342358
343359 self ._tools_cache [tool_name ] = {
344360 'tool_path' : tool_path ,
@@ -398,6 +414,9 @@ def _run_idf_tools_install(self, tools_json_path: str, idf_tools_path: str) -> b
398414
399415 def _check_tool_version (self , tool_name : str ) -> bool :
400416 """Check if the installed tool version matches the required version."""
417+ # Clean up versioned directories FIRST, before any version checks
418+ self ._cleanup_versioned_tool_directories (tool_name )
419+
401420 paths = self ._get_tool_paths (tool_name )
402421
403422 try :
@@ -489,17 +508,10 @@ def _handle_existing_tool(
489508 logger .debug (f"Tool { tool_name } found with correct version" )
490509 return True
491510
492- # Wrong version, reinstall - remove similar paths too
511+ # Wrong version, reinstall - cleanup is already done in _check_tool_version
493512 logger .info (f"Reinstalling { tool_name } due to version mismatch" )
494-
495- tool_base_name = os .path .basename (paths ['tool_path' ])
496- packages_dir = os .path .dirname (paths ['tool_path' ])
497-
498- # Remove similar directories with version suffixes FIRST (e.g., xtensa@src, xtensa.12232)
499- safe_remove_directory_pattern (packages_dir , f"{ tool_base_name } @*" )
500- safe_remove_directory_pattern (packages_dir , f"{ tool_base_name } .*" )
501-
502- # Then remove the main tool directory (if it still exists)
513+
514+ # Remove the main tool directory (if it still exists after cleanup)
503515 safe_remove_directory (paths ['tool_path' ])
504516
505517 return self .install_tool (tool_name , retry_count + 1 )
0 commit comments