Skip to content

Commit 2cff560

Browse files
committed
feat: adding patch version to the esp-idf manager
1 parent 3504879 commit 2cff560

2 files changed

Lines changed: 146 additions & 0 deletions

File tree

bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
import java.io.BufferedReader;
88
import java.io.File;
99
import java.io.InputStreamReader;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
1012
import java.util.ArrayList;
1113
import java.util.List;
14+
import java.util.regex.Matcher;
15+
import java.util.regex.Pattern;
1216

1317
import org.eclipse.core.runtime.Platform;
1418

@@ -25,12 +29,86 @@
2529
*/
2630
public class ToolsUtility
2731
{
32+
private static final Pattern IDF_VERSION_MAJOR_PATTERN = Pattern.compile("IDF_VERSION_MAJOR\\s+(\\d+)"); //$NON-NLS-1$
33+
private static final Pattern IDF_VERSION_MINOR_PATTERN = Pattern.compile("IDF_VERSION_MINOR\\s+(\\d+)"); //$NON-NLS-1$
34+
private static final Pattern IDF_VERSION_PATCH_PATTERN = Pattern.compile("IDF_VERSION_PATCH\\s+(\\d+)"); //$NON-NLS-1$
35+
36+
/**
37+
* Detects the ESP-IDF version for the given installation.
38+
* <p>
39+
* Prefers the full {@code MAJOR.MINOR.PATCH} read directly from {@code tools/cmake/version.cmake}
40+
* under the installation's {@code IDF_PATH}. This is intentionally not derived from the
41+
* {@code ESP_IDF_VERSION} environment variable: ESP-IDF and EIM define that variable as
42+
* {@code MAJOR.MINOR} only (components consume it in Kconfig, e.g. {@code Kconfig.idf_v5.5.in}), so
43+
* it never carries the patch component. When {@code version.cmake} cannot be read, falls back to the
44+
* {@code ESP_IDF_VERSION} value printed by the activation script.
45+
*/
2846
public static String getIdfVersion(EimInstallationModel installation)
2947
{
48+
String versionFromCMake = readIdfVersionFromCMake(installation.getPath());
49+
if (!StringUtil.isEmpty(versionFromCMake))
50+
{
51+
return versionFromCMake;
52+
}
53+
3054
return installation.getActivationScript().map(ToolsUtility::readIdfVersionFromScript)
3155
.orElse(StringUtil.EMPTY);
3256
}
3357

58+
private static String readIdfVersionFromCMake(String idfPath)
59+
{
60+
if (StringUtil.isEmpty(idfPath))
61+
{
62+
return StringUtil.EMPTY;
63+
}
64+
65+
Path versionCMakeFile = Path.of(idfPath, "tools", "cmake", "version.cmake"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
66+
return parseVersionCMake(versionCMakeFile);
67+
}
68+
69+
/**
70+
* Parses {@code version.cmake} and returns {@code MAJOR.MINOR.PATCH} (or {@code MAJOR.MINOR} when
71+
* the patch entry is absent). Returns an empty string when the file is missing or the required
72+
* major/minor entries cannot be found.
73+
*/
74+
public static String parseVersionCMake(Path versionCMakeFile)
75+
{
76+
if (versionCMakeFile == null || !Files.isRegularFile(versionCMakeFile))
77+
{
78+
return StringUtil.EMPTY;
79+
}
80+
81+
try
82+
{
83+
String content = Files.readString(versionCMakeFile);
84+
String major = firstGroup(IDF_VERSION_MAJOR_PATTERN, content);
85+
String minor = firstGroup(IDF_VERSION_MINOR_PATTERN, content);
86+
if (major == null || minor == null)
87+
{
88+
return StringUtil.EMPTY;
89+
}
90+
91+
String patch = firstGroup(IDF_VERSION_PATCH_PATTERN, content);
92+
if (patch == null)
93+
{
94+
return major + "." + minor; //$NON-NLS-1$
95+
}
96+
97+
return major + "." + minor + "." + patch; //$NON-NLS-1$ //$NON-NLS-2$
98+
}
99+
catch (Exception e)
100+
{
101+
Logger.log(e);
102+
return StringUtil.EMPTY;
103+
}
104+
}
105+
106+
private static String firstGroup(Pattern pattern, String content)
107+
{
108+
Matcher matcher = pattern.matcher(content);
109+
return matcher.find() ? matcher.group(1) : null;
110+
}
111+
34112
private static String readIdfVersionFromScript(String activationScript)
35113
{
36114
String espIdfVersion = StringUtil.EMPTY;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*******************************************************************************
2+
* Copyright 2026 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
3+
* Use is subject to license terms.
4+
*******************************************************************************/
5+
package com.espressif.idf.core.tools.test;
6+
7+
import java.io.IOException;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
11+
import org.junit.jupiter.api.Assertions;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.io.TempDir;
14+
15+
import com.espressif.idf.core.tools.util.ToolsUtility;
16+
17+
/**
18+
* Unit tests for {@link ToolsUtility#parseVersionCMake(Path)}.
19+
*/
20+
public class ToolsUtilityTest
21+
{
22+
@Test
23+
void full_version_includes_patch(@TempDir Path tempDir) throws IOException
24+
{
25+
Path file = writeVersionCMake(tempDir, """
26+
set(IDF_VERSION_MAJOR 6)
27+
set(IDF_VERSION_MINOR 0)
28+
set(IDF_VERSION_PATCH 1)
29+
""");
30+
Assertions.assertEquals("6.0.1", ToolsUtility.parseVersionCMake(file));
31+
}
32+
33+
@Test
34+
void missing_patch_falls_back_to_major_minor(@TempDir Path tempDir) throws IOException
35+
{
36+
Path file = writeVersionCMake(tempDir, """
37+
set(IDF_VERSION_MAJOR 5)
38+
set(IDF_VERSION_MINOR 3)
39+
""");
40+
Assertions.assertEquals("5.3", ToolsUtility.parseVersionCMake(file));
41+
}
42+
43+
@Test
44+
void missing_minor_returns_empty(@TempDir Path tempDir) throws IOException
45+
{
46+
Path file = writeVersionCMake(tempDir, "set(IDF_VERSION_MAJOR 6)\n");
47+
Assertions.assertEquals("", ToolsUtility.parseVersionCMake(file));
48+
}
49+
50+
@Test
51+
void nonexistent_file_returns_empty(@TempDir Path tempDir)
52+
{
53+
Assertions.assertEquals("", ToolsUtility.parseVersionCMake(tempDir.resolve("version.cmake")));
54+
}
55+
56+
@Test
57+
void null_file_returns_empty()
58+
{
59+
Assertions.assertEquals("", ToolsUtility.parseVersionCMake(null));
60+
}
61+
62+
private static Path writeVersionCMake(Path dir, String content) throws IOException
63+
{
64+
Path file = dir.resolve("version.cmake");
65+
Files.writeString(file, content);
66+
return file;
67+
}
68+
}

0 commit comments

Comments
 (0)