Skip to content

Commit 8f57051

Browse files
committed
Merge branch 'fix/idf_tools_install_tool_version' into 'master'
fix(tools): fixed command `idf_tools.py install tool@version` Closes IDF-12845 See merge request espressif/esp-idf!39588
2 parents f638d5e + bd0873f commit 8f57051

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

.gitlab/ci/host-test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ test_cli_installer:
113113
script:
114114
# Tools must be downloaded for testing
115115
# We could use "idf_tools.py download all", but we don't want to install clang because of its huge size
116-
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
116+
# cmake@version that is supported
117+
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake [email protected]
117118
- cd ${IDF_PATH}/tools/test_idf_tools
118119
- python3 -m pip install jsonschema
119120
- python3 ./test_idf_tools.py -v

.gitlab/ci/test-win.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ test_cli_installer_win:
3535
timeout: 3h
3636
script:
3737
# Tools must be downloaded for testing
38-
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
38+
# cmake@version that is supported
39+
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake [email protected]
3940
- cd ${IDF_PATH}\tools\test_idf_tools
4041
- python -m pip install jsonschema
4142
- python .\test_idf_tools.py

tools/idf_tools.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,17 +1089,37 @@ def get_recommended_version(self) -> Optional[str]:
10891089

10901090
def get_preferred_installed_version(self) -> Optional[str]:
10911091
"""
1092-
Get the preferred installed version of the tool. If more versions installed, return the highest.
1092+
Get the preferred installed version of the tool.
1093+
If more versions installed, return recommended version if exists, otherwise return the highest supported version
10931094
"""
1094-
recommended_versions = [
1095+
1096+
try:
1097+
self.find_installed_versions()
1098+
except ToolBinaryError:
1099+
pass
1100+
1101+
if self.get_recommended_version() in self.versions_installed:
1102+
return self.get_recommended_version()
1103+
1104+
supported_installed_versions = [
10951105
k
10961106
for k in self.versions_installed
1097-
if self.versions[k].status == IDFToolVersion.STATUS_RECOMMENDED
1107+
if self.versions[k].status == IDFToolVersion.STATUS_SUPPORTED
10981108
and self.versions[k].compatible_with_platform(self._platform)
10991109
]
1100-
assert len(recommended_versions) <= 1
1101-
if recommended_versions:
1102-
return recommended_versions[0]
1110+
sorted_supported_installed_versions = sorted(
1111+
supported_installed_versions, key=lambda x: self.versions[x], reverse=True
1112+
)
1113+
if sorted_supported_installed_versions:
1114+
warn(
1115+
''.join(
1116+
[
1117+
f'Using supported version {sorted_supported_installed_versions[0]} for tool {self.name} ',
1118+
f'as recommended version {self.get_recommended_version()} is not installed.',
1119+
]
1120+
)
1121+
)
1122+
return sorted_supported_installed_versions[0]
11031123
return None
11041124

11051125
def find_installed_versions(self) -> None:
@@ -1152,8 +1172,7 @@ def find_installed_versions(self) -> None:
11521172
else:
11531173
if ver_str != version:
11541174
warn(f'tool {self.name} version {version} is installed, but has reported version {ver_str}')
1155-
else:
1156-
self.versions_installed.append(version)
1175+
self.versions_installed.append(version)
11571176
if tool_error:
11581177
raise ToolBinaryError
11591178

@@ -1900,6 +1919,9 @@ def expand_tools_arg(tools_spec: List[str], overall_tools: OrderedDict, targets:
19001919

19011920
# Filtering by ESP_targets
19021921
tools = [k for k in tools if overall_tools[k].is_supported_for_any_of_targets(targets)]
1922+
1923+
# Processing specific version of tool - defined with '@'
1924+
tools.extend([tool_pattern for tool_pattern in tools_spec if '@' in tool_pattern])
19031925
return tools
19041926

19051927

@@ -2250,10 +2272,6 @@ def process_tool(
22502272
tool_export_paths: List[str] = []
22512273
tool_export_vars: Dict[str, str] = {}
22522274

2253-
try:
2254-
tool.find_installed_versions()
2255-
except ToolBinaryError:
2256-
pass
22572275
recommended_version_to_use = tool.get_preferred_installed_version()
22582276

22592277
if not tool.is_executable and recommended_version_to_use:
@@ -3132,7 +3150,7 @@ def action_uninstall(args: Any) -> None:
31323150
os.listdir(os.path.join(tools_path, tool)) if os.path.isdir(os.path.join(tools_path, tool)) else []
31333151
)
31343152
try:
3135-
unused_versions = [x for x in tool_versions if x != tools_info[tool].get_recommended_version()]
3153+
unused_versions = [x for x in tool_versions if x != tools_info[tool].get_preferred_installed_version()]
31363154
except (
31373155
KeyError
31383156
): # When tool that is not supported by tools_info (tools.json) anymore, remove the whole tool file
@@ -3188,7 +3206,7 @@ def action_uninstall(args: Any) -> None:
31883206
tool_name, tool_version = tool_spec.split('@', 1)
31893207
tool_obj = tools_info_for_platform[tool_name]
31903208
if tool_version is None:
3191-
tool_version = tool_obj.get_recommended_version()
3209+
tool_version = tool_obj.get_preferred_installed_version()
31923210
# mypy-checks
31933211
if tool_version is not None:
31943212
archive_version = tool_obj.versions[tool_version].get_download_for_platform(CURRENT_PLATFORM)

tools/test_idf_tools/test_idf_tools.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,32 @@ def test_export_recommended_version_cmake(self):
313313

314314
self.assertIn(os.path.join(tool_to_test, tool_version), output)
315315

316+
def test_export_supported_version_cmake(self):
317+
tool_to_test = 'cmake'
318+
supported_version = ''
319+
recommended_version = ''
320+
for tool in self.tools_dict['tools']:
321+
if tool['name'] != tool_to_test:
322+
continue
323+
for version in tool['versions']:
324+
if version['status'] == 'supported':
325+
supported_version = version['name']
326+
elif version['status'] == 'recommended':
327+
recommended_version = version['name']
328+
329+
self.run_idf_tools_with_action(['install'])
330+
output = self.run_idf_tools_with_action(['install', f'{tool_to_test}@{supported_version}'])
331+
self.assert_tool_installed(output, tool_to_test, supported_version)
332+
333+
# Remove the recommended version folder installed by install command (in case of Windows)
334+
recommended_version_folder = os.path.join(self.temp_tools_dir, 'tools', tool_to_test, recommended_version)
335+
if os.path.exists(recommended_version_folder):
336+
shutil.rmtree(recommended_version_folder)
337+
338+
output = self.run_idf_tools_with_action(['export'])
339+
self.assertIn(os.path.join(tool_to_test, supported_version), output)
340+
self.assertNotIn(os.path.join(tool_to_test, recommended_version), output)
341+
316342
def test_export_prefer_system_cmake(self):
317343
tool_to_test = 'cmake'
318344
self.run_idf_tools_with_action(['install'])

0 commit comments

Comments
 (0)