From 00dc7000ffb8036eb59e140403bab30ac94d40c4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:17:35 +0200 Subject: [PATCH 01/18] initial attempt to check version of tl-install --- platform.py | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/platform.py b/platform.py index 39eccbae5..50d33adc9 100644 --- a/platform.py +++ b/platform.py @@ -159,6 +159,84 @@ def packages_dir(self) -> str: self._packages_dir = config.get("platformio", "packages_dir") return self._packages_dir + def _check_tl_install_version(self) -> bool: + """ + Prüft ob tl-install in der korrekten Version installiert ist. + Installiert die korrekte Version falls erforderlich. + """ + tl_install_name = "tl-install" + + # Hole die erforderliche Version aus platform.json + required_version = self.packages.get(tl_install_name, {}).get("version") + if not required_version: + logger.debug(f"Keine Versionsprüfung für {tl_install_name} erforderlich") + return True + + # Prüfe ob das Tool bereits installiert ist + tl_install_path = os.path.join(self.packages_dir, tl_install_name) + package_json_path = os.path.join(tl_install_path, "package.json") + + if not os.path.exists(package_json_path): + logger.info(f"{tl_install_name} nicht installiert, installiere Version {required_version}") + return self._install_tl_install(required_version) + + # Lese die installierte Version + try: + with open(package_json_path, 'r', encoding='utf-8') as f: + package_data = json.load(f) + + installed_version = package_data.get("version") + if not installed_version: + logger.warning(f"Installierte Version für {tl_install_name} unbekannt") + return self._install_tl_install(required_version) + + # Vergleiche Versionen + if installed_version != required_version: + logger.info( + f"Versionsfehler für {tl_install_name}: " + f"{installed_version} != {required_version}, installiere korrekte Version" + ) + return self._install_tl_install(required_version) + + logger.debug(f"{tl_install_name} Version {installed_version} ist korrekt") + return True + + except (json.JSONDecodeError, FileNotFoundError) as e: + logger.error(f"Fehler beim Lesen der Paketdaten für {tl_install_name}: {e}") + return self._install_tl_install(required_version) + + def _install_tl_install(self, version: str) -> bool: + """ + Installiert tl-install in der angegebenen Version. + """ + tl_install_name = "tl-install" + tl_install_path = os.path.join(self.packages_dir, tl_install_name) + + try: + # Entferne alte Installation + if os.path.exists(tl_install_path): + logger.info(f"Entferne alte {tl_install_name} Installation") + safe_remove_directory(tl_install_path) + + # Entferne auch versionierte Verzeichnisse + safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}@*") + safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}.*") + + # Installiere neue Version + logger.info(f"Installiere {tl_install_name} Version {version}") + self.packages[tl_install_name]["optional"] = False + self.packages[tl_install_name]["version"] = version + + # Verwende den Package Manager für die Installation + pm.install(f"{tl_install_name}@{version}") + + logger.info(f"{tl_install_name} Version {version} erfolgreich installiert") + return True + + except Exception as e: + logger.error(f"Fehler bei der Installation von {tl_install_name}: {e}") + return False + def _get_tool_paths(self, tool_name: str) -> Dict[str, str]: """Get centralized path calculation for tools with caching.""" if tool_name not in self._tools_cache: @@ -424,6 +502,11 @@ def _configure_mcu_toolchains( def _configure_installer(self) -> None: """Configure the ESP-IDF tools installer.""" + + if not self._check_tl_install_version(): + logger.error("Error during tl-install version check / installation") + return + installer_path = os.path.join( self.packages_dir, "tl-install", "tools", "idf_tools.py" ) From 4e92eafc298f45a962a0e21f0e8c44946ca37921 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:30:32 +0200 Subject: [PATCH 02/18] ident --- platform.py | 72 ++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/platform.py b/platform.py index 50d33adc9..995e063cd 100644 --- a/platform.py +++ b/platform.py @@ -160,50 +160,50 @@ def packages_dir(self) -> str: return self._packages_dir def _check_tl_install_version(self) -> bool: - """ - Prüft ob tl-install in der korrekten Version installiert ist. - Installiert die korrekte Version falls erforderlich. - """ - tl_install_name = "tl-install" + """ + Prüft ob tl-install in der korrekten Version installiert ist. + Installiert die korrekte Version falls erforderlich. + """ + tl_install_name = "tl-install" - # Hole die erforderliche Version aus platform.json - required_version = self.packages.get(tl_install_name, {}).get("version") - if not required_version: - logger.debug(f"Keine Versionsprüfung für {tl_install_name} erforderlich") - return True + # Hole die erforderliche Version aus platform.json + required_version = self.packages.get(tl_install_name, {}).get("version") + if not required_version: + logger.debug(f"Keine Versionsprüfung für {tl_install_name} erforderlich") + return True - # Prüfe ob das Tool bereits installiert ist - tl_install_path = os.path.join(self.packages_dir, tl_install_name) - package_json_path = os.path.join(tl_install_path, "package.json") + # Prüfe ob das Tool bereits installiert ist + tl_install_path = os.path.join(self.packages_dir, tl_install_name) + package_json_path = os.path.join(tl_install_path, "package.json") - if not os.path.exists(package_json_path): - logger.info(f"{tl_install_name} nicht installiert, installiere Version {required_version}") - return self._install_tl_install(required_version) + if not os.path.exists(package_json_path): + logger.info(f"{tl_install_name} nicht installiert, installiere Version {required_version}") + return self._install_tl_install(required_version) - # Lese die installierte Version - try: - with open(package_json_path, 'r', encoding='utf-8') as f: - package_data = json.load(f) + # Lese die installierte Version + try: + with open(package_json_path, 'r', encoding='utf-8') as f: + package_data = json.load(f) - installed_version = package_data.get("version") - if not installed_version: - logger.warning(f"Installierte Version für {tl_install_name} unbekannt") - return self._install_tl_install(required_version) + installed_version = package_data.get("version") + if not installed_version: + logger.warning(f"Installierte Version für {tl_install_name} unbekannt") + return self._install_tl_install(required_version) - # Vergleiche Versionen - if installed_version != required_version: - logger.info( - f"Versionsfehler für {tl_install_name}: " - f"{installed_version} != {required_version}, installiere korrekte Version" - ) - return self._install_tl_install(required_version) + # Vergleiche Versionen + if installed_version != required_version: + logger.info( + f"Versionsfehler für {tl_install_name}: " + f"{installed_version} != {required_version}, installiere korrekte Version" + ) + return self._install_tl_install(required_version) - logger.debug(f"{tl_install_name} Version {installed_version} ist korrekt") - return True + logger.debug(f"{tl_install_name} Version {installed_version} ist korrekt") + return True - except (json.JSONDecodeError, FileNotFoundError) as e: - logger.error(f"Fehler beim Lesen der Paketdaten für {tl_install_name}: {e}") - return self._install_tl_install(required_version) + except (json.JSONDecodeError, FileNotFoundError) as e: + logger.error(f"Fehler beim Lesen der Paketdaten für {tl_install_name}: {e}") + return self._install_tl_install(required_version) def _install_tl_install(self, version: str) -> bool: """ From fa6643ed05eb9dbd5a07547181091631c4d346f2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:42:10 +0200 Subject: [PATCH 03/18] Only URL for tl-install --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 995e063cd..bf65f9221 100644 --- a/platform.py +++ b/platform.py @@ -228,7 +228,7 @@ def _install_tl_install(self, version: str) -> bool: self.packages[tl_install_name]["version"] = version # Verwende den Package Manager für die Installation - pm.install(f"{tl_install_name}@{version}") + pm.install(version) logger.info(f"{tl_install_name} Version {version} erfolgreich installiert") return True From 651997b383e3ca8509117ad299fd7ab9d203daa3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:45:11 +0200 Subject: [PATCH 04/18] add version to tl-install --- platform.json | 1 + 1 file changed, 1 insertion(+) diff --git a/platform.json b/platform.json index 0622c715a..d819aa650 100644 --- a/platform.json +++ b/platform.json @@ -99,6 +99,7 @@ "type": "tool", "optional": false, "owner": "pioarduino", + "package-version": "5.1.0", "version": "https://github.com/pioarduino/esp_install/releases/download/v5.1.0/esp_install-v5.1.0.zip" }, "contrib-piohome": { From 3f8cb3bb680798b500d40c088e159f17c27e8bcd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:46:57 +0200 Subject: [PATCH 05/18] rename tl-install -> tool-esp_install --- platform.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.json b/platform.json index d819aa650..2b951f37b 100644 --- a/platform.json +++ b/platform.json @@ -95,7 +95,7 @@ "package-version": "5.0.1", "version": "https://github.com/pioarduino/registry/releases/download/0.0.1/esptoolpy-v5.0.1.zip" }, - "tl-install": { + "tool-esp_install": { "type": "tool", "optional": false, "owner": "pioarduino", From 9d4f7b0c3d08063149424d76e85b41ee2e775b77 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:52:12 +0200 Subject: [PATCH 06/18] rename tl-install -> tool-esp_install --- platform.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform.py b/platform.py index bf65f9221..befb174ff 100644 --- a/platform.py +++ b/platform.py @@ -164,7 +164,7 @@ def _check_tl_install_version(self) -> bool: Prüft ob tl-install in der korrekten Version installiert ist. Installiert die korrekte Version falls erforderlich. """ - tl_install_name = "tl-install" + tl_install_name = "tool-esp_install" # Hole die erforderliche Version aus platform.json required_version = self.packages.get(tl_install_name, {}).get("version") @@ -209,7 +209,7 @@ def _install_tl_install(self, version: str) -> bool: """ Installiert tl-install in der angegebenen Version. """ - tl_install_name = "tl-install" + tl_install_name = "tool-esp_install" tl_install_path = os.path.join(self.packages_dir, tl_install_name) try: From 031f53a58fbd2188e3f2ca8398c2318c54b5c74e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:06:48 +0200 Subject: [PATCH 07/18] Update platform.py --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index befb174ff..7f75ff00f 100644 --- a/platform.py +++ b/platform.py @@ -260,7 +260,7 @@ def _get_tool_paths(self, tool_name: str) -> Dict[str, str]: 'tools_json_path': os.path.join(tool_path, "tools.json"), 'piopm_path': os.path.join(tool_path, ".piopm"), 'idf_tools_path': os.path.join( - self.packages_dir, "tl-install", "tools", "idf_tools.py" + self.packages_dir, "tool-esp_install", "tools", "idf_tools.py" ) } return self._tools_cache[tool_name] From 7da085351000fe58e5b9859ba88f45273de58415 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 29 Jul 2025 12:19:30 +0200 Subject: [PATCH 08/18] replace fixed name with var for tool-esp_install --- platform.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/platform.py b/platform.py index 7f75ff00f..3b2b507f5 100644 --- a/platform.py +++ b/platform.py @@ -33,6 +33,7 @@ SUBPROCESS_TIMEOUT = 300 DEFAULT_DEBUG_SPEED = "5000" DEFAULT_APP_OFFSET = "0x10000" +tl_install_name = "tool-esp_install" ARDUINO_ESP32_PACKAGE_URL = "https://raw.githubusercontent.com/espressif/arduino-esp32/master/package/package_esp32_index.template.json" # MCUs that support ESP-builtin debug @@ -161,10 +162,9 @@ def packages_dir(self) -> str: def _check_tl_install_version(self) -> bool: """ - Prüft ob tl-install in der korrekten Version installiert ist. + Prüft ob tool-esp_install in der korrekten Version installiert ist. Installiert die korrekte Version falls erforderlich. """ - tl_install_name = "tool-esp_install" # Hole die erforderliche Version aus platform.json required_version = self.packages.get(tl_install_name, {}).get("version") @@ -207,9 +207,8 @@ def _check_tl_install_version(self) -> bool: def _install_tl_install(self, version: str) -> bool: """ - Installiert tl-install in der angegebenen Version. + Installiert tool-esp_install in der angegebenen Version. """ - tl_install_name = "tool-esp_install" tl_install_path = os.path.join(self.packages_dir, tl_install_name) try: @@ -260,7 +259,7 @@ def _get_tool_paths(self, tool_name: str) -> Dict[str, str]: 'tools_json_path': os.path.join(tool_path, "tools.json"), 'piopm_path': os.path.join(tool_path, ".piopm"), 'idf_tools_path': os.path.join( - self.packages_dir, "tool-esp_install", "tools", "idf_tools.py" + self.packages_dir, tl_install_name, "tools", "idf_tools.py" ) } return self._tools_cache[tool_name] @@ -504,14 +503,14 @@ def _configure_installer(self) -> None: """Configure the ESP-IDF tools installer.""" if not self._check_tl_install_version(): - logger.error("Error during tl-install version check / installation") + logger.error("Error during tool-esp_install version check / installation") return installer_path = os.path.join( - self.packages_dir, "tl-install", "tools", "idf_tools.py" + self.packages_dir, tl_install_name, "tools", "idf_tools.py" ) if os.path.exists(installer_path): - self.packages["tl-install"]["optional"] = True + self.packages[tl_install_name]["optional"] = True def _install_esptool_package(self) -> None: """Install esptool package required for all builds.""" From f92fbda06b31b77b5e37645fb430146768251fdd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:53:31 +0200 Subject: [PATCH 09/18] prevent reinstall of too-esp_install at every run --- platform.py | 154 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 43 deletions(-) diff --git a/platform.py b/platform.py index 3b2b507f5..0188a4bd6 100644 --- a/platform.py +++ b/platform.py @@ -162,78 +162,139 @@ def packages_dir(self) -> str: def _check_tl_install_version(self) -> bool: """ - Prüft ob tool-esp_install in der korrekten Version installiert ist. - Installiert die korrekte Version falls erforderlich. + Check if tool-esp_install is installed in the correct version. + Install the correct version only if version differs. + + Returns: + bool: True if correct version is available, False on error """ - - # Hole die erforderliche Version aus platform.json + + # Get required version from platform.json required_version = self.packages.get(tl_install_name, {}).get("version") if not required_version: - logger.debug(f"Keine Versionsprüfung für {tl_install_name} erforderlich") + logger.debug(f"No version check required for {tl_install_name}") return True - - # Prüfe ob das Tool bereits installiert ist + + # Check if tool is already installed tl_install_path = os.path.join(self.packages_dir, tl_install_name) package_json_path = os.path.join(tl_install_path, "package.json") - + if not os.path.exists(package_json_path): - logger.info(f"{tl_install_name} nicht installiert, installiere Version {required_version}") + logger.info(f"{tl_install_name} not installed, installing version {required_version}") return self._install_tl_install(required_version) - - # Lese die installierte Version + + # Read installed version try: with open(package_json_path, 'r', encoding='utf-8') as f: package_data = json.load(f) - + installed_version = package_data.get("version") if not installed_version: - logger.warning(f"Installierte Version für {tl_install_name} unbekannt") + logger.warning(f"Installed version for {tl_install_name} unknown, installing {required_version}") return self._install_tl_install(required_version) - - # Vergleiche Versionen - if installed_version != required_version: + + # IMPORTANT: Compare versions correctly + if self._compare_tl_install_versions(installed_version, required_version): + logger.debug(f"{tl_install_name} version {installed_version} is already correctly installed") + # IMPORTANT: Set package as available, but do NOT reinstall + self.packages[tl_install_name]["optional"] = True + return True + else: logger.info( - f"Versionsfehler für {tl_install_name}: " - f"{installed_version} != {required_version}, installiere korrekte Version" + f"Version mismatch for {tl_install_name}: " + f"installed={installed_version}, required={required_version}, installing correct version" ) return self._install_tl_install(required_version) - - logger.debug(f"{tl_install_name} Version {installed_version} ist korrekt") - return True - + except (json.JSONDecodeError, FileNotFoundError) as e: - logger.error(f"Fehler beim Lesen der Paketdaten für {tl_install_name}: {e}") + logger.error(f"Error reading package data for {tl_install_name}: {e}") return self._install_tl_install(required_version) + def _compare_tl_install_versions(self, installed: str, required: str) -> bool: + """ + Compare installed and required version of tool-esp_install. + + Args: + installed: Currently installed version string + required: Required version string from platform.json + + Returns: + bool: True if versions match, False otherwise + """ + # For URL-based versions: Extract version string from URL + installed_clean = self._extract_version_from_url(installed) + required_clean = self._extract_version_from_url(required) + + logger.debug(f"Version comparison: installed='{installed_clean}' vs required='{required_clean}'") + + return installed_clean == required_clean + + def _extract_version_from_url(self, version_string: str) -> str: + """ + Extract version information from URL or return version directly. + + Args: + version_string: Version string or URL containing version + + Returns: + str: Extracted version string + """ + if version_string.startswith(('http://', 'https://')): + # Extract version from URL like: .../v5.1.0/esp_install-v5.1.0.zip + import re + version_match = re.search(r'v(\d+\.\d+\.\d+)', version_string) + if version_match: + return version_match.group(1) # Returns "5.1.0" + else: + # Fallback: Use entire URL + return version_string + else: + # Direct version number + return version_string.strip() + def _install_tl_install(self, version: str) -> bool: """ - Installiert tool-esp_install in der angegebenen Version. + Install tool-esp_install ONLY when necessary. + + Args: + version: Version string or URL to install + + Returns: + bool: True if installation successful, False otherwise """ tl_install_path = os.path.join(self.packages_dir, tl_install_name) - + try: - # Entferne alte Installation + # Remove old installation completely if os.path.exists(tl_install_path): - logger.info(f"Entferne alte {tl_install_name} Installation") + logger.info(f"Removing old {tl_install_name} installation") safe_remove_directory(tl_install_path) - - # Entferne auch versionierte Verzeichnisse + + # Remove versioned directories as well safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}@*") safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}.*") - - # Installiere neue Version - logger.info(f"Installiere {tl_install_name} Version {version}") + + # Install new version + logger.info(f"Installing {tl_install_name} version {version}") + + # Set package configuration self.packages[tl_install_name]["optional"] = False self.packages[tl_install_name]["version"] = version - - # Verwende den Package Manager für die Installation + + # Install via package manager pm.install(version) - - logger.info(f"{tl_install_name} Version {version} erfolgreich installiert") - return True - + + # Verify installation + if os.path.exists(os.path.join(tl_install_path, "package.json")): + logger.info(f"{tl_install_name} successfully installed and verified") + self.packages[tl_install_name]["optional"] = True + return True + else: + logger.error(f"{tl_install_name} installation failed - package.json not found") + return False + except Exception as e: - logger.error(f"Fehler bei der Installation von {tl_install_name}: {e}") + logger.error(f"Error installing {tl_install_name}: {e}") return False def _get_tool_paths(self, tool_name: str) -> Dict[str, str]: @@ -418,7 +479,7 @@ def _handle_existing_tool( return self.install_tool(tool_name, retry_count + 1) def _configure_arduino_framework(self, frameworks: List[str]) -> None: - """Configure Arduino framework""" + """Configure Arduino framework dependencies.""" if "arduino" not in frameworks: return @@ -500,17 +561,23 @@ def _configure_mcu_toolchains( self.install_tool("tool-openocd-esp32") def _configure_installer(self) -> None: - """Configure the ESP-IDF tools installer.""" - + """Configure the ESP-IDF tools installer with proper version checking.""" + + # Check version - installs only when needed if not self._check_tl_install_version(): logger.error("Error during tool-esp_install version check / installation") return + # Check if idf_tools.py is available installer_path = os.path.join( self.packages_dir, tl_install_name, "tools", "idf_tools.py" ) + if os.path.exists(installer_path): + logger.debug(f"{tl_install_name} is available and ready") self.packages[tl_install_name]["optional"] = True + else: + logger.warning(f"idf_tools.py not found in {installer_path}") def _install_esptool_package(self) -> None: """Install esptool package required for all builds.""" @@ -545,7 +612,7 @@ def _ensure_mklittlefs_version(self) -> None: os.remove(piopm_path) logger.info(f"Incompatible mklittlefs version {version} removed (required: 3.x)") except (json.JSONDecodeError, KeyError) as e: - logger.error(f"Error reading mklittlefs package data: {e}") + logger.error(f"Error reading mklittlefs package {e}") def _setup_mklittlefs_for_download(self) -> None: """Setup mklittlefs for download functionality with version 4.x.""" @@ -797,3 +864,4 @@ def configure_debug_session(self, debug_config): f'{build_extra_data.get("application_offset", DEFAULT_APP_OFFSET)} verify' ) debug_config.load_cmds = load_cmds + From cc783274f6b6b64157edaea45d336cac085e7da0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 29 Jul 2025 13:19:54 +0200 Subject: [PATCH 10/18] remove old tl-install --- platform.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/platform.py b/platform.py index 0188a4bd6..1e972a218 100644 --- a/platform.py +++ b/platform.py @@ -269,21 +269,22 @@ def _install_tl_install(self, version: str) -> bool: if os.path.exists(tl_install_path): logger.info(f"Removing old {tl_install_name} installation") safe_remove_directory(tl_install_path) - - # Remove versioned directories as well - safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}@*") - safe_remove_directory_pattern(self.packages_dir, f"{tl_install_name}.*") - + + # Remove maybe old existing version of tl-install too + old_tl_install_path = os.path.join(self.packages_dir, "tl-install") + if os.path.exists(old_tl_install_path): + safe_remove_directory(old_tl_install_path) + # Install new version logger.info(f"Installing {tl_install_name} version {version}") - + # Set package configuration self.packages[tl_install_name]["optional"] = False self.packages[tl_install_name]["version"] = version - + # Install via package manager pm.install(version) - + # Verify installation if os.path.exists(os.path.join(tl_install_path, "package.json")): logger.info(f"{tl_install_name} successfully installed and verified") From 1af767d1fc2ae02dd74f736cdbef6609743d6a4a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 10:50:35 +0200 Subject: [PATCH 11/18] add safe_copy_directory() --- platform.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platform.py b/platform.py index 1e972a218..87ccb4517 100644 --- a/platform.py +++ b/platform.py @@ -142,6 +142,15 @@ def safe_copy_file(src: str, dst: str) -> bool: return True +@safe_file_operation +def safe_copy_directory(src: str, dst: str) -> bool: + """Safely copy directories with error handling.""" + os.makedirs(os.path.dirname(dst), exist_ok=True) + shutil.copytree(src, dst, dirs_exist_ok=True) + logger.debug(f"Directory copied: {src} -> {dst}") + return True + + class Espressif32Platform(PlatformBase): """ESP32 platform implementation for PlatformIO with optimized toolchain management.""" From 34ca164bb11388507fc26f0fc4e784ec2aec5534 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:27:17 +0200 Subject: [PATCH 12/18] Handle backwards compability for tl-install --- platform.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/platform.py b/platform.py index 87ccb4517..da04f1562 100644 --- a/platform.py +++ b/platform.py @@ -263,50 +263,54 @@ def _extract_version_from_url(self, version_string: str) -> str: def _install_tl_install(self, version: str) -> bool: """ - Install tool-esp_install ONLY when necessary. - + Install tool-esp_install ONLY when necessary + and handles backwards compability for tl-install. + Args: version: Version string or URL to install - + Returns: bool: True if installation successful, False otherwise """ tl_install_path = os.path.join(self.packages_dir, tl_install_name) - + old_tl_install_path = os.path.join(self.packages_dir, "tl-install") + try: - # Remove old installation completely + old_tl_install_exists = os.path.exists(old_tl_install_path) + if old_tl_install_exists: + # remove outdated tl-install + safe_remove_directory(old_tl_install_path) + if os.path.exists(tl_install_path): logger.info(f"Removing old {tl_install_name} installation") safe_remove_directory(tl_install_path) - # Remove maybe old existing version of tl-install too - old_tl_install_path = os.path.join(self.packages_dir, "tl-install") - if os.path.exists(old_tl_install_path): - safe_remove_directory(old_tl_install_path) - - # Install new version logger.info(f"Installing {tl_install_name} version {version}") - - # Set package configuration self.packages[tl_install_name]["optional"] = False self.packages[tl_install_name]["version"] = version - - # Install via package manager pm.install(version) - # Verify installation if os.path.exists(os.path.join(tl_install_path, "package.json")): logger.info(f"{tl_install_name} successfully installed and verified") self.packages[tl_install_name]["optional"] = True + + # Handle old tl-install to keep backwards compability + if old_tl_install_exists: + # Copy tool-esp_install content to tl-install location + if safe_copy_directory(tl_install_path, old_tl_install_path): + logger.info(f"Content copied from {tl_install_name} to old tl-install location") + else: + logger.warning(f"Failed to copy content to old tl-install location") return True else: logger.error(f"{tl_install_name} installation failed - package.json not found") return False - + except Exception as e: logger.error(f"Error installing {tl_install_name}: {e}") return False + def _get_tool_paths(self, tool_name: str) -> Dict[str, str]: """Get centralized path calculation for tools with caching.""" if tool_name not in self._tools_cache: From b29a5886650a9a69df522c725ba688bb28421a5d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:50:29 +0200 Subject: [PATCH 13/18] remove piopm file in tl-install folder --- platform.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform.py b/platform.py index da04f1562..26d187447 100644 --- a/platform.py +++ b/platform.py @@ -110,6 +110,15 @@ def wrapper(*args, **kwargs): return wrapper +@safe_file_operation +def safe_remove_file(path: str) -> bool: + """Safely remove a file with error handling.""" + if os.path.exists(path) and os.path.isfile(path): + os.remove(path) + logger.debug(f"File removed: {path}") + return True + + @safe_file_operation def safe_remove_directory(path: str) -> bool: """Safely remove directories with error handling.""" @@ -299,6 +308,8 @@ def _install_tl_install(self, version: str) -> bool: # Copy tool-esp_install content to tl-install location if safe_copy_directory(tl_install_path, old_tl_install_path): logger.info(f"Content copied from {tl_install_name} to old tl-install location") + tl_piopm_path = os.path.join(old_tl_install_path, ".piopm") + safe_remove_file(tl_piopm_path) else: logger.warning(f"Failed to copy content to old tl-install location") return True From b51adf8b01d9355a5990c646434af1a466171c30 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:07:51 +0200 Subject: [PATCH 14/18] remove .piopm in both tl install folders --- platform.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform.py b/platform.py index 26d187447..6264c13a5 100644 --- a/platform.py +++ b/platform.py @@ -308,7 +308,9 @@ def _install_tl_install(self, version: str) -> bool: # Copy tool-esp_install content to tl-install location if safe_copy_directory(tl_install_path, old_tl_install_path): logger.info(f"Content copied from {tl_install_name} to old tl-install location") - tl_piopm_path = os.path.join(old_tl_install_path, ".piopm") + old_tl_piopm_path = os.path.join(old_tl_install_path, ".piopm") + safe_remove_file(old_tl_piopm_path) + tl_piopm_path = os.path.join(tl_install_path, ".piopm") safe_remove_file(tl_piopm_path) else: logger.warning(f"Failed to copy content to old tl-install location") From 78e425db2c2a4e017ecb5cc1154719fbb1623a9f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:19:24 +0200 Subject: [PATCH 15/18] remove tool-esp_install .piopm installation indicator we dont need and it makes issues --- platform.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform.py b/platform.py index 6264c13a5..37e1d00e7 100644 --- a/platform.py +++ b/platform.py @@ -298,6 +298,9 @@ def _install_tl_install(self, version: str) -> bool: self.packages[tl_install_name]["optional"] = False self.packages[tl_install_name]["version"] = version pm.install(version) + # Ensure backward compability by removing pio install status indicator + tl_piopm_path = os.path.join(tl_install_path, ".piopm") + safe_remove_file(tl_piopm_path) if os.path.exists(os.path.join(tl_install_path, "package.json")): logger.info(f"{tl_install_name} successfully installed and verified") @@ -308,10 +311,6 @@ def _install_tl_install(self, version: str) -> bool: # Copy tool-esp_install content to tl-install location if safe_copy_directory(tl_install_path, old_tl_install_path): logger.info(f"Content copied from {tl_install_name} to old tl-install location") - old_tl_piopm_path = os.path.join(old_tl_install_path, ".piopm") - safe_remove_file(old_tl_piopm_path) - tl_piopm_path = os.path.join(tl_install_path, ".piopm") - safe_remove_file(tl_piopm_path) else: logger.warning(f"Failed to copy content to old tl-install location") return True From 00d06cf52b9ce0bededcbbbafc8540bb1cb2497e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:53:04 +0200 Subject: [PATCH 16/18] check and remove tl-install piopm always --- platform.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform.py b/platform.py index 37e1d00e7..f3702c1e7 100644 --- a/platform.py +++ b/platform.py @@ -594,6 +594,11 @@ def _configure_installer(self) -> None: logger.error("Error during tool-esp_install version check / installation") return + # Remove pio install marker to avoid issues when switching versions + old_tl_piopm_path = os.path.join(self.packages_dir, "tl-install", ".piopm") + if os.path.exists(old_tl_piopm_path): + safe_remove_file(old_tl_piopm_path) + # Check if idf_tools.py is available installer_path = os.path.join( self.packages_dir, tl_install_name, "tools", "idf_tools.py" From f039e4d0092ff7a1064fa3d490e982d84b738ade Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:10:22 +0200 Subject: [PATCH 17/18] remove not needed function from print --- platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.py b/platform.py index f3702c1e7..aff274cba 100644 --- a/platform.py +++ b/platform.py @@ -312,7 +312,7 @@ def _install_tl_install(self, version: str) -> bool: if safe_copy_directory(tl_install_path, old_tl_install_path): logger.info(f"Content copied from {tl_install_name} to old tl-install location") else: - logger.warning(f"Failed to copy content to old tl-install location") + logger.warning("Failed to copy content to old tl-install location") return True else: logger.error(f"{tl_install_name} installation failed - package.json not found") From f210a1f6b2abb576dee46fd8b3997cf757cc38ff Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:15:00 +0200 Subject: [PATCH 18/18] removed last line --- platform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/platform.py b/platform.py index aff274cba..8d6e73b7d 100644 --- a/platform.py +++ b/platform.py @@ -895,4 +895,3 @@ def configure_debug_session(self, debug_config): f'{build_extra_data.get("application_offset", DEFAULT_APP_OFFSET)} verify' ) debug_config.load_cmds = load_cmds -