From c1ad58faa9b7ea3348982417aead678331a8928a Mon Sep 17 00:00:00 2001 From: alirana01 Date: Wed, 19 Jul 2023 17:48:20 +0200 Subject: [PATCH 01/12] refactoring the classes to the required areas to cleanup code --- .../META-INF/MANIFEST.MF | 3 +++ .../IToolsInstallationWizardConstants.java | 2 +- .../idf/core}/tools/IToolsJsonKeys.java | 2 +- .../espressif/idf/core}/tools/JsonKey.java | 2 +- .../idf/core}/tools/ToolsJsonParser.java | 8 ++++---- .../idf/core/tools}/ToolsPlatformMapping.java | 20 +++++++++---------- .../idf/core/tools/util}/ToolsUtility.java | 4 ++-- .../espressif/idf/core}/tools/vo/ToolsVO.java | 2 +- .../idf/core}/tools/vo/VersionDetailsVO.java | 2 +- .../idf/core}/tools/vo/VersionsVO.java | 2 +- .../tools/ManageToolsInstallationHandler.java | 2 +- .../ui/tools/ToolsInstallationHandler.java | 7 ++++--- .../ui/tools/wizard/ToolsManagerWizard.java | 1 + .../wizard/ToolsManagerWizardDialog.java | 1 + .../tools/wizard/pages/InstallEspIdfPage.java | 2 +- .../wizard/pages/InstallPreRquisitePage.java | 2 +- .../ManageToolsInstallationWizardPage.java | 13 ++++++------ 17 files changed, 41 insertions(+), 34 deletions(-) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard => com.espressif.idf.core/src/com/espressif/idf/core/tools}/IToolsInstallationWizardConstants.java (94%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/IToolsJsonKeys.java (96%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/JsonKey.java (92%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/ToolsJsonParser.java (97%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages => com.espressif.idf.core/src/com/espressif/idf/core/tools}/ToolsPlatformMapping.java (69%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui/tools => com.espressif.idf.core/src/com/espressif/idf/core/tools/util}/ToolsUtility.java (99%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/vo/ToolsVO.java (99%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/vo/VersionDetailsVO.java (96%) rename bundles/{com.espressif.idf.ui/src/com/espressif/idf/ui => com.espressif.idf.core/src/com/espressif/idf/core}/tools/vo/VersionsVO.java (97%) diff --git a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF index a2513c20e..1f321f866 100644 --- a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF @@ -35,6 +35,9 @@ Export-Package: com.espressif.idf.core, com.espressif.idf.core.logging, com.espressif.idf.core.resources, com.espressif.idf.core.toolchain, + com.espressif.idf.core.tools, + com.espressif.idf.core.tools.util, + com.espressif.idf.core.tools.vo, com.espressif.idf.core.util, com.espressif.idf.core.variable, org.json.simple, diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/IToolsInstallationWizardConstants.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java similarity index 94% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/IToolsInstallationWizardConstants.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java index 795fd41c8..f98b2d88c 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/IToolsInstallationWizardConstants.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsInstallationWizardConstants.java @@ -2,7 +2,7 @@ * Copyright 2022 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools.wizard; +package com.espressif.idf.core.tools; /** * Interface to store the constants related to tools management wizard diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/IToolsJsonKeys.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java similarity index 96% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/IToolsJsonKeys.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java index 087ce03a7..4f49dbff1 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/IToolsJsonKeys.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java @@ -1,4 +1,4 @@ -package com.espressif.idf.ui.tools; +package com.espressif.idf.core.tools; /** * Keys in the tools.json file mentioned here for the better usage diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/JsonKey.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java similarity index 92% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/JsonKey.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java index 06b58ad3d..0eca4e6ff 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/JsonKey.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/JsonKey.java @@ -1,4 +1,4 @@ -package com.espressif.idf.ui.tools; +package com.espressif.idf.core.tools; import static java.lang.annotation.ElementType.FIELD; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJsonParser.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java similarity index 97% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJsonParser.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java index 15baf5437..4f4da939f 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsJsonParser.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java @@ -2,7 +2,7 @@ * Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools; +package com.espressif.idf.core.tools; import java.io.BufferedReader; import java.io.FileReader; @@ -16,10 +16,10 @@ import org.eclipse.core.runtime.Platform; +import com.espressif.idf.core.tools.vo.ToolsVO; +import com.espressif.idf.core.tools.vo.VersionDetailsVO; +import com.espressif.idf.core.tools.vo.VersionsVO; import com.espressif.idf.core.util.IDFUtil; -import com.espressif.idf.ui.tools.vo.ToolsVO; -import com.espressif.idf.ui.tools.vo.VersionDetailsVO; -import com.espressif.idf.ui.tools.vo.VersionsVO; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ToolsPlatformMapping.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java similarity index 69% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ToolsPlatformMapping.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java index aaa6454d0..853e4363f 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ToolsPlatformMapping.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsPlatformMapping.java @@ -2,7 +2,7 @@ * Copyright 2022 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools.wizard.pages; +package com.espressif.idf.core.tools; import java.util.Arrays; @@ -20,15 +20,15 @@ public enum ToolsPlatformMapping { // @formatter:off - WIN32("win32", Platform.OS_WIN32,Platform.ARCH_X86), - WIN64("win64", Platform.OS_WIN32, Platform.ARCH_X86_64), - MACOS("macos", Platform.OS_MACOSX, Platform.ARCH_X86_64), - MACOSARM64("macos-arm64", Platform.OS_MACOSX, Platform.ARCH_AARCH64), - LINUXAMD64("linux-amd64", Platform.OS_LINUX, Platform.ARCH_X86_64), - LINUXARM64("linux-arm64", Platform.OS_LINUX, "arm64"), - LINUXARMEL("linux-armel", Platform.OS_LINUX, "armel"), - LINUXARMHF("linux-armhf", Platform.OS_LINUX, "armhf"), - LINUXI686("linux-i686", Platform.OS_LINUX, "i686"); + WIN32("win32", Platform.OS_WIN32,Platform.ARCH_X86), //$NON-NLS-1$ + WIN64("win64", Platform.OS_WIN32, Platform.ARCH_X86_64), //$NON-NLS-1$ + MACOS("macos", Platform.OS_MACOSX, Platform.ARCH_X86_64), //$NON-NLS-1$ + MACOSARM64("macos-arm64", Platform.OS_MACOSX, Platform.ARCH_AARCH64), //$NON-NLS-1$ + LINUXAMD64("linux-amd64", Platform.OS_LINUX, Platform.ARCH_X86_64), //$NON-NLS-1$ + LINUXARM64("linux-arm64", Platform.OS_LINUX, "arm64"), //$NON-NLS-1$ //$NON-NLS-2$ + LINUXARMEL("linux-armel", Platform.OS_LINUX, "armel"), //$NON-NLS-1$ //$NON-NLS-2$ + LINUXARMHF("linux-armhf", Platform.OS_LINUX, "armhf"), //$NON-NLS-1$ //$NON-NLS-2$ + LINUXI686("linux-i686", Platform.OS_LINUX, "i686"); //$NON-NLS-1$ //$NON-NLS-2$ // @formatter:on diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsUtility.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java similarity index 99% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsUtility.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java index 6ee6d2457..4c3c267f9 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsUtility.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java @@ -2,7 +2,7 @@ * Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools; +package com.espressif.idf.core.tools.util; import java.io.BufferedInputStream; import java.io.File; @@ -32,8 +32,8 @@ import com.espressif.idf.core.IDFEnvironmentVariables; import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.tools.vo.ToolsVO; import com.espressif.idf.core.util.FileUtil; -import com.espressif.idf.ui.tools.vo.ToolsVO; /** * Utility class for Tools Management operations diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/ToolsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java similarity index 99% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/ToolsVO.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java index 4210a3ae2..89c3cb3b5 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/ToolsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java @@ -2,7 +2,7 @@ * Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools.vo; +package com.espressif.idf.core.tools.vo; import java.text.DecimalFormat; import java.util.List; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionDetailsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java similarity index 96% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionDetailsVO.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java index d47f8abc4..340c71d6b 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionDetailsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java @@ -2,7 +2,7 @@ * Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools.vo; +package com.espressif.idf.core.tools.vo; import java.text.DecimalFormat; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java similarity index 97% rename from bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionsVO.java rename to bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java index 263536152..2441f8a7f 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/vo/VersionsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java @@ -2,7 +2,7 @@ * Copyright 2021 Espressif Systems (Shanghai) PTE LTD. All rights reserved. * Use is subject to license terms. *******************************************************************************/ -package com.espressif.idf.ui.tools.vo; +package com.espressif.idf.core.tools.vo; import java.util.Map; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageToolsInstallationHandler.java index 9a5708b16..5860dfc94 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ManageToolsInstallationHandler.java @@ -14,8 +14,8 @@ import org.eclipse.ui.PlatformUI; import com.espressif.idf.core.IDFEnvironmentVariables; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.ui.UIPlugin; -import com.espressif.idf.ui.tools.wizard.IToolsInstallationWizardConstants; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizard; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizardDialog; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index 0d55ce13f..707d78208 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -41,12 +41,13 @@ import com.espressif.idf.core.ProcessBuilderFactory; import com.espressif.idf.core.logging.Logger; import com.espressif.idf.core.toolchain.ESPToolChainManager; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; +import com.espressif.idf.core.tools.util.ToolsUtility; +import com.espressif.idf.core.tools.vo.ToolsVO; +import com.espressif.idf.core.tools.vo.VersionsVO; import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; -import com.espressif.idf.ui.tools.vo.ToolsVO; -import com.espressif.idf.ui.tools.vo.VersionsVO; -import com.espressif.idf.ui.tools.wizard.IToolsInstallationWizardConstants; import com.espressif.idf.ui.tools.wizard.pages.ManageToolsInstallationWizardPage; import com.espressif.idf.ui.update.InstallToolsHandler; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java index 536a583c2..c56553145 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java @@ -16,6 +16,7 @@ import org.osgi.service.prefs.Preferences; import com.espressif.idf.core.IDFEnvironmentVariables; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.Messages; import com.espressif.idf.ui.tools.wizard.pages.IToolsWizardPage; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizardDialog.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizardDialog.java index 4baea888c..5273eb77c 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizardDialog.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizardDialog.java @@ -19,6 +19,7 @@ import org.eclipse.swt.widgets.Shell; import com.espressif.idf.core.IDFEnvironmentVariables; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.wizard.pages.IToolsWizardPage; import com.espressif.idf.ui.tools.wizard.pages.ManageToolsInstallationWizardPage; diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java index 70a60dac7..51c3ded89 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallEspIdfPage.java @@ -33,13 +33,13 @@ import com.espressif.idf.core.IDFEnvironmentVariables; import com.espressif.idf.core.IDFVersion; import com.espressif.idf.core.IDFVersionsReader; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.GitDownloadAndCloneThread; import com.espressif.idf.ui.tools.LogMessagesThread; import com.espressif.idf.ui.tools.Messages; -import com.espressif.idf.ui.tools.wizard.IToolsInstallationWizardConstants; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizard; /** diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallPreRquisitePage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallPreRquisitePage.java index 28350597e..e369ec75b 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallPreRquisitePage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/InstallPreRquisitePage.java @@ -38,13 +38,13 @@ import com.espressif.idf.core.ProcessBuilderFactory; import com.espressif.idf.core.SystemExecutableFinder; import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; import com.espressif.idf.core.util.GitWinRegistryReader; import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.PyWinRegistryReader; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.Messages; -import com.espressif.idf.ui.tools.wizard.IToolsInstallationWizardConstants; /** * Install initial tools page for git and python configs diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java index e9cb821e4..f8638fed8 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java @@ -44,17 +44,18 @@ import com.espressif.idf.core.IDFEnvironmentVariables; import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; +import com.espressif.idf.core.tools.ToolsJsonParser; +import com.espressif.idf.core.tools.ToolsPlatformMapping; +import com.espressif.idf.core.tools.util.ToolsUtility; +import com.espressif.idf.core.tools.vo.ToolsVO; +import com.espressif.idf.core.tools.vo.VersionDetailsVO; +import com.espressif.idf.core.tools.vo.VersionsVO; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.LogMessagesThread; import com.espressif.idf.ui.tools.Messages; import com.espressif.idf.ui.tools.ToolsInstallationHandler; -import com.espressif.idf.ui.tools.ToolsJsonParser; -import com.espressif.idf.ui.tools.ToolsUtility; -import com.espressif.idf.ui.tools.vo.ToolsVO; -import com.espressif.idf.ui.tools.vo.VersionDetailsVO; -import com.espressif.idf.ui.tools.vo.VersionsVO; -import com.espressif.idf.ui.tools.wizard.IToolsInstallationWizardConstants; import com.espressif.idf.ui.tools.wizard.ToolsManagerWizardDialog; /** From d35368761ae36f3bc0849192d19dea3014e85676 Mon Sep 17 00:00:00 2001 From: alirana01 Date: Wed, 19 Jul 2023 17:55:01 +0200 Subject: [PATCH 02/12] libs moved after refactoring --- bundles/com.espressif.idf.core/.classpath | 3 +++ bundles/com.espressif.idf.core/META-INF/MANIFEST.MF | 6 +++++- bundles/com.espressif.idf.core/build.properties | 5 ++++- .../lib/commonmark-0.16.1.jar | Bin .../lib/commons-compress-1.21-javadoc.jar | Bin .../lib/commons-compress-1.21.jar | Bin .../lib/xz-1.9-javadoc.jar | Bin .../lib/xz-1.9-sources.jar | Bin .../lib/xz-1.9.jar | Bin bundles/com.espressif.idf.ui/.classpath | 11 ----------- bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF | 3 --- bundles/com.espressif.idf.ui/build.properties | 3 --- 12 files changed, 12 insertions(+), 19 deletions(-) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/commonmark-0.16.1.jar (100%) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/commons-compress-1.21-javadoc.jar (100%) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/commons-compress-1.21.jar (100%) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/xz-1.9-javadoc.jar (100%) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/xz-1.9-sources.jar (100%) rename bundles/{com.espressif.idf.ui => com.espressif.idf.core}/lib/xz-1.9.jar (100%) diff --git a/bundles/com.espressif.idf.core/.classpath b/bundles/com.espressif.idf.core/.classpath index e23fef426..8c764389c 100644 --- a/bundles/com.espressif.idf.core/.classpath +++ b/bundles/com.espressif.idf.core/.classpath @@ -16,6 +16,9 @@ + + + diff --git a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF index 1f321f866..1ebb61305 100644 --- a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF @@ -50,4 +50,8 @@ Bundle-ClassPath: ., lib/snakeyaml-1.30.jar, lib/opencsv-5.7.0.jar, lib/commons-beanutils-1.9.4.jar, - lib/commons-text-1.10.0.jar + lib/commons-text-1.10.0.jar, + lib/commons-compress-1.21.jar, + lib/xz-1.9.jar, + lib/commonmark-0.16.1.jar +Import-Package: org.eclipse.embedcdt.core diff --git a/bundles/com.espressif.idf.core/build.properties b/bundles/com.espressif.idf.core/build.properties index 761266e91..799c6cc6b 100644 --- a/bundles/com.espressif.idf.core/build.properties +++ b/bundles/com.espressif.idf.core/build.properties @@ -11,4 +11,7 @@ bin.includes = META-INF/,\ lib/opencsv-5.7.0.jar,\ lib/commons-lang3-3.12.0.jar,\ lib/commons-beanutils-1.9.4.jar,\ - lib/commons-text-1.10.0.jar + lib/commons-text-1.10.0.jar,\ + lib/commonmark-0.16.1.jar,\ + lib/commons-compress-1.21.jar,\ + lib/xz-1.9.jar diff --git a/bundles/com.espressif.idf.ui/lib/commonmark-0.16.1.jar b/bundles/com.espressif.idf.core/lib/commonmark-0.16.1.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/commonmark-0.16.1.jar rename to bundles/com.espressif.idf.core/lib/commonmark-0.16.1.jar diff --git a/bundles/com.espressif.idf.ui/lib/commons-compress-1.21-javadoc.jar b/bundles/com.espressif.idf.core/lib/commons-compress-1.21-javadoc.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/commons-compress-1.21-javadoc.jar rename to bundles/com.espressif.idf.core/lib/commons-compress-1.21-javadoc.jar diff --git a/bundles/com.espressif.idf.ui/lib/commons-compress-1.21.jar b/bundles/com.espressif.idf.core/lib/commons-compress-1.21.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/commons-compress-1.21.jar rename to bundles/com.espressif.idf.core/lib/commons-compress-1.21.jar diff --git a/bundles/com.espressif.idf.ui/lib/xz-1.9-javadoc.jar b/bundles/com.espressif.idf.core/lib/xz-1.9-javadoc.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/xz-1.9-javadoc.jar rename to bundles/com.espressif.idf.core/lib/xz-1.9-javadoc.jar diff --git a/bundles/com.espressif.idf.ui/lib/xz-1.9-sources.jar b/bundles/com.espressif.idf.core/lib/xz-1.9-sources.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/xz-1.9-sources.jar rename to bundles/com.espressif.idf.core/lib/xz-1.9-sources.jar diff --git a/bundles/com.espressif.idf.ui/lib/xz-1.9.jar b/bundles/com.espressif.idf.core/lib/xz-1.9.jar similarity index 100% rename from bundles/com.espressif.idf.ui/lib/xz-1.9.jar rename to bundles/com.espressif.idf.core/lib/xz-1.9.jar diff --git a/bundles/com.espressif.idf.ui/.classpath b/bundles/com.espressif.idf.ui/.classpath index f2410d7a8..87e039413 100644 --- a/bundles/com.espressif.idf.ui/.classpath +++ b/bundles/com.espressif.idf.ui/.classpath @@ -1,23 +1,12 @@ - - - - - - - - - - - diff --git a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF index 951b37830..629b1624f 100644 --- a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF @@ -52,8 +52,5 @@ Export-Package: com.espressif.idf.ui, com.espressif.idf.ui.tracing, com.espressif.idf.ui.update Bundle-ClassPath: ., - lib/commons-compress-1.21.jar, - lib/xz-1.9.jar, - lib/commonmark-0.16.1.jar, lib/ini4j-0.5.4.jar, lib/gson-2.8.7.jar diff --git a/bundles/com.espressif.idf.ui/build.properties b/bundles/com.espressif.idf.ui/build.properties index adc1de2d2..e3d67fc78 100644 --- a/bundles/com.espressif.idf.ui/build.properties +++ b/bundles/com.espressif.idf.ui/build.properties @@ -5,15 +5,12 @@ bin.includes = META-INF/,\ plugin.xml,\ icons/,\ templates/,\ - lib/commonmark-0.16.1.jar,\ lib/ini4j-0.5.4.jar,\ OSGI-INF/,\ go.css,\ index.html,\ lib/gson-2.8.7.jar,\ OSGI-INF/l10n/bundle.properties,\ - lib/commons-compress-1.21.jar,\ introcontent.xml,\ index.html,\ go.css,\ - lib/xz-1.9.jar From c75e5e73d1fce453806bacc6555b06730270fa93 Mon Sep 17 00:00:00 2001 From: alirana01 Date: Wed, 19 Jul 2023 17:55:41 +0200 Subject: [PATCH 03/12] NLS tag fix --- .../src/com/espressif/idf/core/tools/util/ToolsUtility.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java index 4c3c267f9..6b2827cf9 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java @@ -159,7 +159,7 @@ public static void extractTarGz(String tarFile, String outputDir) { Files.createDirectories(pathEntryOutput.getParent()); Files.copy(tararchiveinputstream, pathEntryOutput, StandardCopyOption.REPLACE_EXISTING); - Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); + Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); //$NON-NLS-1$ } } @@ -206,9 +206,9 @@ else if (archiveentry.isDirectory()) } else { - System.out.println(pathEntryOutput.toString() + " " + archiveentry.getSize()); + System.out.println(pathEntryOutput.toString() + " " + archiveentry.getSize()); //$NON-NLS-1$ Files.copy(tararchiveinputstream, pathEntryOutput, StandardCopyOption.REPLACE_EXISTING); - Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); + Runtime.getRuntime().exec("/bin/chmod 755 ".concat(pathEntryOutput.toString())); //$NON-NLS-1$ } } tararchiveinputstream.close(); From 95e1ab3b6924f267ac6a4ed581b80fb99cbe2141 Mon Sep 17 00:00:00 2001 From: alirana01 Date: Wed, 19 Jul 2023 18:38:00 +0200 Subject: [PATCH 04/12] initial boilerplate for the tools validation --- .../idf/core/tools/IToolsJsonKeys.java | 2 + .../idf/core/tools/ToolsJsonParser.java | 16 ++ .../idf/core/tools/util/ToolsUtility.java | 1 - .../espressif/idf/core/tools/vo/ToolsVO.java | 17 ++- .../ui/tools/ToolsInstallationHandler.java | 139 +++++++++++++----- .../ui/tools/wizard/ToolsManagerWizard.java | 5 +- .../ManageToolsInstallationWizardPage.java | 6 +- 7 files changed, 143 insertions(+), 43 deletions(-) diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java index 4f49dbff1..bf8bc42ea 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/IToolsJsonKeys.java @@ -22,6 +22,8 @@ public interface IToolsJsonKeys String VERSION_CMD_KEY = "version_cmd"; //$NON-NLS-1$ + String VERSION_REGEX = "version_regex"; //$NON-NLS-1$ + String SUPPORTED_TARGETS_KEY = "supported_targets"; //$NON-NLS-1$ String NAME_KEY = "name"; //$NON-NLS-1$ diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java index 4f4da939f..bb35f5d14 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsJsonParser.java @@ -9,6 +9,7 @@ import java.io.InputStreamReader; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,11 +38,14 @@ public class ToolsJsonParser { private Gson gson; private List toolsList; + private List requiredToolsList; + private static final String[] REQUIRED_TOOLS = new String[] {"cmake", "dfu-util", "ninja"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ public ToolsJsonParser() { gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create(); toolsList = new ArrayList<>(); + requiredToolsList = new ArrayList<>(); } public void loadJson() throws Exception @@ -50,6 +54,7 @@ public void loadJson() throws Exception JsonReader jsonReader = new JsonReader(new FileReader(IDFUtil.getIDFToolsJsonFileForInstallation())); JsonObject jsonObject = gson.fromJson(jsonReader, JsonObject.class); JsonArray jsonArray = jsonObject.get(IToolsJsonKeys.TOOLS_KEY).getAsJsonArray(); + List reqToolsNamesList = Arrays.asList(REQUIRED_TOOLS); for (int i = 0; i < jsonArray.size(); i++) { JsonObject toolsJsonObject = jsonArray.get(i).getAsJsonObject(); @@ -72,6 +77,7 @@ public void loadJson() throws Exception getStringsListFromJsonArray(toolsJsonObject.get(IToolsJsonKeys.SUPPORTED_TARGETS_KEY).getAsJsonArray())); } toolsVO.setVersionCmd(getStringsListFromJsonArray(toolsJsonObject.get(IToolsJsonKeys.VERSION_CMD_KEY).getAsJsonArray())); + toolsVO.setVersionRegex(toolsJsonObject.get(IToolsJsonKeys.VERSION_REGEX).getAsString()); toolsVO.setVersionVO(getVersions(toolsJsonObject.get(IToolsJsonKeys.VERSIONS_VO_KEY).getAsJsonArray())); toolsVO.setVersion(jsonObject.get(IToolsJsonKeys.VERSION_KEY).getAsString()); JsonElement jsonElement = toolsJsonObject.get(IToolsJsonKeys.PLATFORM_OVERRIDES_KEY); @@ -81,6 +87,10 @@ public void loadJson() throws Exception } toolsList.add(toolsVO); + if (reqToolsNamesList.contains(toolsVO.getName())) + { + requiredToolsList.add(toolsVO); + } } } @@ -219,4 +229,10 @@ public List getToolsList() { return toolsList; } + + public List getRequiredToolsList() + { + return requiredToolsList; + + } } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java index 6b2827cf9..f8876b2ba 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java @@ -223,7 +223,6 @@ else if (archiveentry.isDirectory()) } } - private static void createHardLinks(Path link, Path target) { try diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java index 89c3cb3b5..563231f40 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java @@ -10,8 +10,8 @@ import org.eclipse.core.runtime.Platform; -import com.espressif.idf.ui.tools.IToolsJsonKeys; -import com.espressif.idf.ui.tools.JsonKey; +import com.espressif.idf.core.tools.IToolsJsonKeys; +import com.espressif.idf.core.tools.JsonKey; /** * Bean class for tools information from json @@ -47,6 +47,9 @@ public class ToolsVO @JsonKey(key_name = IToolsJsonKeys.VERSION_CMD_KEY) private List versionCmd; + + @JsonKey(key_name = IToolsJsonKeys.VERSION_REGEX) + private String versionRegex; @JsonKey(key_name = IToolsJsonKeys.VERSIONS_VO_KEY) private List versionVOs; @@ -213,4 +216,14 @@ public void setInstalled(boolean installed) { this.installed = installed; } + + public String getVersionRegex() + { + return versionRegex; + } + + public void setVersionRegex(String versionRegex) + { + this.versionRegex = versionRegex; + } } diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index 707d78208..7b2f5b12f 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -26,6 +26,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; @@ -77,6 +79,7 @@ public class ToolsInstallationHandler extends Thread private int currentOperation; private List exisitngPathsToRemoveWhenProcessingExportCommands; private List listOfPathsToUpdate; + private List requireToolsVOs; public ToolsInstallationHandler(Queue logQueue, ManageToolsInstallationWizardPage manageToolsInstallationWizardPage, @@ -171,9 +174,10 @@ public void run() * @param operationToPerform operations to perfrom * @throws Exception */ - public void operationToPerform(Map> selectedItems, boolean forceDownload, - int operationToPerform) throws Exception + public void operationToPerform(List requiredToolsVOs, Map> selectedItems, + boolean forceDownload, int operationToPerform) throws Exception { + this.requireToolsVOs = requiredToolsVOs; this.currentOperation = operationToPerform; cancelled = false; setControlsEnabled(false); @@ -380,15 +384,15 @@ private void addPathsToList(String toolPath, String toolName, List expor Path path = Paths.get(toolPath); exisitngPathsToRemoveWhenProcessingExportCommands.add(path.getParent().toString()); - + logQueue.add(Messages.UpdatingPathMessage); StringBuilder exportPathBuilder = new StringBuilder(); exportPathBuilder.append(toolPath); removeExistingToolPath(toolName); - + // sometimes tar.gz archives can result in different types of outputs verify that the // first directory in export paths is present the toolpath - File[] files = new File(toolPath).listFiles(); + File[] files = new File(toolPath).listFiles(); if (files.length >= 1 && exportPaths.size() > 0) { String nameOfPresentDir = files[0].getName(); @@ -410,7 +414,7 @@ private void addPathsToList(String toolPath, String toolName, List expor if (!StringUtil.isEmpty(exportPath)) { exportPathBuilder.append(exportPath); - exportPathBuilder.append(PATH_SPLITOR); + exportPathBuilder.append(PATH_SPLITOR); } } } @@ -556,7 +560,7 @@ public Boolean call() throws Exception { espMainFolder.mkdirs(); } - + for (ToolsVO toolsVo : selectedItems.keySet()) { if (Thread.interrupted()) @@ -574,10 +578,72 @@ public Boolean call() throws Exception handleWebSocketClientInstall(); copyOpenOcdRules(); IDFUtil.updateEspressifPrefPageOpenocdPath(); + validateToolsInstall(); scopedPreferenceStore.putBoolean(InstallToolsHandler.INSTALL_TOOLS_FLAG, true); return Boolean.TRUE; } + private void validateToolsInstall() + { + for (ToolsVO toolsVO : requireToolsVOs) + { + final List arguments = new ArrayList(); + arguments.addAll(toolsVO.getVersionCmd()); + final String cmd = Messages.AbstractToolsHandler_ExecutingMsg + " " + getCommandString(arguments); + logQueue.add(cmd); + Logger.log(cmd); + final Map environment = new HashMap<>(System.getenv()); + if (environment.containsKey(IDFEnvironmentVariables.PATH)) + { + environment.put(IDFEnvironmentVariables.PATH, + idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH)); + } + else if (environment.containsKey("Path")) + { + environment.put("Path", idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH)); + } + final ProcessBuilderFactory processRunner = new ProcessBuilderFactory(); + try + { + final IStatus status = processRunner.runInBackground(arguments, + org.eclipse.core.runtime.Path.fromOSString( + idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH)), + environment); + if (status == null) + { + Logger.log(IDFCorePlugin.getPlugin(), IDFCorePlugin.errorStatus("Status can't be null", null)); //$NON-NLS-1$ + return; + } + + final String cmdOutput = status.getMessage(); + Logger.log(cmdOutput); + logQueue.add(cmdOutput); + + Pattern pattern = Pattern.compile(toolsVO.getVersionRegex()); + Matcher matcher = pattern.matcher(cmdOutput); + if (matcher.find()) + { + String match = matcher.group(); + if (!match.equals(toolsVO.getVersion())) + { + Logger.log("Version Mismatch for " + toolsVO.getName() + " IDF required: " + + toolsVO.getVersion() + " Found: " + match); + logQueue.add("Version Mismatch for " + toolsVO.getName() + " IDF required: " + + toolsVO.getVersion() + " Found: " + match); + } + else + { + // TODO: Handle the case when the tool was not installed and is required + } + } + } + catch (IOException e1) + { + Logger.log(IDFCorePlugin.getPlugin(), e1); + } + } + } + private void configEnv() { // Enable IDF_COMPONENT_MANAGER by default @@ -600,29 +666,30 @@ private void runToolsExport(final String gitExePath) Logger.log(cmd); final Map environment = new HashMap<>(System.getenv()); - + StringBuilder paths = new StringBuilder(); - + for (Path toolPath : listOfPathsToUpdate) { paths.append(toolPath.toAbsolutePath().toString()); paths.append(File.pathSeparatorChar); } - + if (gitExePath != null) { paths.append(gitExePath); paths.append(File.pathSeparator); } - + final ProcessBuilderFactory processRunner = new ProcessBuilderFactory(); - + try { - final IStatus status = processRunner.runInBackground(arguments, - org.eclipse.core.runtime.Path. - fromOSString(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH)), - environment); + final IStatus status = processRunner + .runInBackground(arguments, + org.eclipse.core.runtime.Path.fromOSString( + idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH)), + environment); if (status == null) { Logger.log(IDFCorePlugin.getPlugin(), IDFCorePlugin.errorStatus("Status can't be null", null)); //$NON-NLS-1$ @@ -633,7 +700,7 @@ private void runToolsExport(final String gitExePath) final String exportCmdOp = status.getMessage(); Logger.log(exportCmdOp); logQueue.add(exportCmdOp); - + processExportCmdOutput(exportCmdOp, gitExePath, paths); } catch (IOException e1) @@ -643,7 +710,8 @@ private void runToolsExport(final String gitExePath) } - private void processExportCmdOutput(final String exportCmdOp, final String gitExecutablePath, final StringBuilder paths) + private void processExportCmdOutput(final String exportCmdOp, final String gitExecutablePath, + final StringBuilder paths) { // process export command output final String[] exportEntries = exportCmdOp.split("\n"); //$NON-NLS-1$ @@ -656,10 +724,9 @@ private void processExportCmdOutput(final String exportCmdOp, final String gitEx final String msg = MessageFormat.format("Key: {0} Value: {1}", keyValue[0], keyValue[1]); //$NON-NLS-1$ Logger.log(msg); - String key = keyValue[0]; String value = keyValue[1]; - + if (key.equals(IDFEnvironmentVariables.PATH)) { Logger.log("idf_tools.py ignoring PATH value"); //$NON-NLS-1$ @@ -670,17 +737,18 @@ private void processExportCmdOutput(final String exportCmdOp, final String gitEx idfEnvironmentVariables.addEnvVariable(key, value); } } - - // Appending the virtual python env scripts manually to + // Appending the virtual python env scripts manually to // path as the dependency on the python export script is removed slowly StringBuilder pythonVirtualEnvPath = new StringBuilder(); - pythonVirtualEnvPath.append(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)); + pythonVirtualEnvPath + .append(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)); pythonVirtualEnvPath.append(File.separatorChar); pythonVirtualEnvPath.append("Scripts"); //$NON-NLS-1$ pythonVirtualEnvPath.append(File.separatorChar); pythonVirtualEnvPath.append(File.pathSeparator); - pythonVirtualEnvPath.append(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)); + pythonVirtualEnvPath + .append(idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PYTHON_ENV_PATH)); pythonVirtualEnvPath.append(File.separatorChar); pythonVirtualEnvPath.append("bin"); //$NON-NLS-1$ pythonVirtualEnvPath.append(File.separatorChar); @@ -690,25 +758,24 @@ private void processExportCmdOutput(final String exportCmdOp, final String gitEx pythonVirtualEnvPath.append("tools"); //$NON-NLS-1$ pythonVirtualEnvPath.append(File.separatorChar); pythonVirtualEnvPath.append(File.pathSeparator); - + paths.append(pythonVirtualEnvPath.toString()); - replacePathVariable(paths); + replacePathVariable(paths); } private void replacePathVariable(StringBuilder paths) { String existingPath = idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH); - + if (StringUtil.isEmpty(existingPath)) { idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.PATH, paths.toString()); return; } - Map environment = System.getenv(); String systemPath = StringUtil.EMPTY; - + if (environment.containsKey(IDFEnvironmentVariables.PATH)) { systemPath = environment.get(IDFEnvironmentVariables.PATH); @@ -717,7 +784,7 @@ else if (environment.containsKey("Path")) { systemPath = environment.get("Path"); } - + List pathsToAppend = new ArrayList(); String newPaths = paths.toString(); int separatorIndex = existingPath.indexOf(File.pathSeparator); @@ -729,11 +796,11 @@ else if (environment.containsKey("Path")) { pathsToAppend.add(path); } - + prevIndex = separatorIndex + 1; separatorIndex = existingPath.indexOf(File.pathSeparator, separatorIndex + 1); } - + if (separatorIndex == -1) { separatorIndex = existingPath.length(); @@ -743,18 +810,18 @@ else if (environment.containsKey("Path")) pathsToAppend.add(path); } } - - + for (String path : pathsToAppend) { paths.append(path); paths.append(File.pathSeparator); } - + paths.append(systemPath); - + idfEnvironmentVariables.addEnvVariable(IDFEnvironmentVariables.PATH, paths.toString()); } + private void copyOpenOcdRules() { if (Platform.getOS().equals(Platform.OS_LINUX) diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java index c56553145..537a5bba6 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/ToolsManagerWizard.java @@ -17,6 +17,7 @@ import com.espressif.idf.core.IDFEnvironmentVariables; import com.espressif.idf.core.tools.IToolsInstallationWizardConstants; +import com.espressif.idf.core.tools.ToolsJsonParser; import com.espressif.idf.ui.UIPlugin; import com.espressif.idf.ui.tools.Messages; import com.espressif.idf.ui.tools.wizard.pages.IToolsWizardPage; @@ -39,6 +40,7 @@ public class ToolsManagerWizard extends Wizard private Preferences scopedPreferenceStore; private Map existingVarMap; private boolean exisitngInstallPreferencesStatus; + private ToolsJsonParser toolsJsonParser; public ToolsManagerWizard(Map existingVarMap, boolean exisitngInstallPreferencesStatus) { @@ -48,6 +50,7 @@ public ToolsManagerWizard(Map existingVarMap, boolean exisitngIn scopedPreferenceStore.putBoolean(IToolsInstallationWizardConstants.INSTALL_TOOLS_FLAG, false); this.existingVarMap = existingVarMap; this.exisitngInstallPreferencesStatus = exisitngInstallPreferencesStatus; + toolsJsonParser = new ToolsJsonParser(); } @Override @@ -61,7 +64,7 @@ public void addPages() { installPreRquisitePage = new InstallPreRquisitePage(); installEspIdfPage = new InstallEspIdfPage(); - manageToolsInstallationPage = new ManageToolsInstallationWizardPage(parentWizardDialog); + manageToolsInstallationPage = new ManageToolsInstallationWizardPage(parentWizardDialog, toolsJsonParser); addPage(installPreRquisitePage); addPage(installEspIdfPage); addPage(manageToolsInstallationPage); diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java index f8638fed8..e2e0b9c18 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java @@ -111,12 +111,12 @@ public class ManageToolsInstallationWizardPage extends WizardPage implements ITo private Button forceDownloadBtn; private Listener[] listenersForFinish; - public ManageToolsInstallationWizardPage(WizardDialog parentWizardDialog) + public ManageToolsInstallationWizardPage(WizardDialog parentWizardDialog, ToolsJsonParser toolsJsonParser) { super(Messages.ManageToolsInstallation); setTitle(Messages.ManageToolsInstallation); setDescription(Messages.ManageToolsInstallationDescription); - toolsJsonParser = new ToolsJsonParser(); + this.toolsJsonParser = toolsJsonParser; this.parentWizardDialog = parentWizardDialog; this.logQueue = new ConcurrentLinkedQueue(); idfEnvironmentVariables = new IDFEnvironmentVariables(); @@ -914,7 +914,7 @@ public void widgetSelected(SelectionEvent e) Map> selectedItems = getSelectedTools(); try { - toolsInstallationHandler.operationToPerform(selectedItems, forceDownloadBtn.getSelection(), + toolsInstallationHandler.operationToPerform(toolsJsonParser.getRequiredToolsList(), selectedItems, forceDownloadBtn.getSelection(), ToolsInstallationHandler.INSTALLING_TOOLS); } catch (Exception e1) From 05da2b999e5e0c63ec76f91ffd83a316a425ea4a Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Thu, 20 Jul 2023 09:57:28 +0200 Subject: [PATCH 05/12] reverted required move of commonmark lib in ui --- bundles/com.espressif.idf.core/.classpath | 1 - bundles/com.espressif.idf.core/META-INF/MANIFEST.MF | 3 +-- bundles/com.espressif.idf.core/build.properties | 1 - bundles/com.espressif.idf.ui/.classpath | 1 + bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF | 3 ++- bundles/com.espressif.idf.ui/build.properties | 1 + .../lib/commonmark-0.16.1.jar | Bin 7 files changed, 5 insertions(+), 5 deletions(-) rename bundles/{com.espressif.idf.core => com.espressif.idf.ui}/lib/commonmark-0.16.1.jar (100%) diff --git a/bundles/com.espressif.idf.core/.classpath b/bundles/com.espressif.idf.core/.classpath index 8c764389c..5469bf4d3 100644 --- a/bundles/com.espressif.idf.core/.classpath +++ b/bundles/com.espressif.idf.core/.classpath @@ -16,7 +16,6 @@ - diff --git a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF index 1ebb61305..5dcffd652 100644 --- a/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.core/META-INF/MANIFEST.MF @@ -52,6 +52,5 @@ Bundle-ClassPath: ., lib/commons-beanutils-1.9.4.jar, lib/commons-text-1.10.0.jar, lib/commons-compress-1.21.jar, - lib/xz-1.9.jar, - lib/commonmark-0.16.1.jar + lib/xz-1.9.jar Import-Package: org.eclipse.embedcdt.core diff --git a/bundles/com.espressif.idf.core/build.properties b/bundles/com.espressif.idf.core/build.properties index 799c6cc6b..dbb089ce8 100644 --- a/bundles/com.espressif.idf.core/build.properties +++ b/bundles/com.espressif.idf.core/build.properties @@ -12,6 +12,5 @@ bin.includes = META-INF/,\ lib/commons-lang3-3.12.0.jar,\ lib/commons-beanutils-1.9.4.jar,\ lib/commons-text-1.10.0.jar,\ - lib/commonmark-0.16.1.jar,\ lib/commons-compress-1.21.jar,\ lib/xz-1.9.jar diff --git a/bundles/com.espressif.idf.ui/.classpath b/bundles/com.espressif.idf.ui/.classpath index 87e039413..c14e15488 100644 --- a/bundles/com.espressif.idf.ui/.classpath +++ b/bundles/com.espressif.idf.ui/.classpath @@ -7,6 +7,7 @@ + diff --git a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF index 629b1624f..8658b5036 100644 --- a/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF +++ b/bundles/com.espressif.idf.ui/META-INF/MANIFEST.MF @@ -53,4 +53,5 @@ Export-Package: com.espressif.idf.ui, com.espressif.idf.ui.update Bundle-ClassPath: ., lib/ini4j-0.5.4.jar, - lib/gson-2.8.7.jar + lib/gson-2.8.7.jar, + lib/commonmark-0.16.1.jar diff --git a/bundles/com.espressif.idf.ui/build.properties b/bundles/com.espressif.idf.ui/build.properties index e3d67fc78..81cee356a 100644 --- a/bundles/com.espressif.idf.ui/build.properties +++ b/bundles/com.espressif.idf.ui/build.properties @@ -6,6 +6,7 @@ bin.includes = META-INF/,\ icons/,\ templates/,\ lib/ini4j-0.5.4.jar,\ + lib/commonmark-0.16.1.jar,\ OSGI-INF/,\ go.css,\ index.html,\ diff --git a/bundles/com.espressif.idf.core/lib/commonmark-0.16.1.jar b/bundles/com.espressif.idf.ui/lib/commonmark-0.16.1.jar similarity index 100% rename from bundles/com.espressif.idf.core/lib/commonmark-0.16.1.jar rename to bundles/com.espressif.idf.ui/lib/commonmark-0.16.1.jar From 389bf4ff74b869414d3b028003a4cbf3963598d1 Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:27:17 +0200 Subject: [PATCH 06/12] basic tools validation code --- .../idf/core/DefaultSystemWrapper.java | 3 - .../com/espressif/idf/core/SystemWrapper.java | 3 + .../idf/core/tools/ToolsSystemWrapper.java | 36 +++++++ .../idf/core/tools/util/ToolsUtility.java | 25 +++++ .../espressif/idf/core/tools/vo/ToolsVO.java | 30 ++++++ .../idf/core/tools/vo/VersionDetailsVO.java | 21 ++++ .../idf/core/tools/vo/VersionsVO.java | 22 ++++ .../espressif/idf/ui/dialogs/URLDialog.java | 85 +++++++++++++++ .../com/espressif/idf/ui/tools/Messages.java | 3 + .../ui/tools/ToolsInstallationHandler.java | 100 ++++++++++++------ .../idf/ui/tools/messages.properties | 3 + .../ManageToolsInstallationWizardPage.java | 3 +- 12 files changed, 299 insertions(+), 35 deletions(-) create mode 100644 bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java create mode 100644 bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/DefaultSystemWrapper.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/DefaultSystemWrapper.java index 9a4967b41..1238bec58 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/DefaultSystemWrapper.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/DefaultSystemWrapper.java @@ -6,9 +6,6 @@ public class DefaultSystemWrapper implements SystemWrapper { - private static final String PATH = "PATH"; //$NON-NLS-1$ - private static final String PATHEXT = "PATHEXT"; //$NON-NLS-1$ - @Override public String getPathEnv() { diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemWrapper.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemWrapper.java index 97007f06d..d545a24e4 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemWrapper.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemWrapper.java @@ -6,6 +6,9 @@ public interface SystemWrapper { + String PATH = "PATH"; //$NON-NLS-1$ + String PATHEXT = "PATHEXT"; //$NON-NLS-1$ + public String getPathEnv(); public String getEnvExecutables(); } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java new file mode 100644 index 000000000..5ac2d9356 --- /dev/null +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/ToolsSystemWrapper.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.core.tools; + +import com.espressif.idf.core.SystemWrapper; + +/** + * Tools System wrapper to make sure to avoid the + * system path when verifying for validation after tools installation + * @author Ali Azam Rana + * + */ +public class ToolsSystemWrapper implements SystemWrapper +{ + private String path; + + public ToolsSystemWrapper(String path) + { + this.path = path; + } + + @Override + public String getPathEnv() + { + return path; + } + + @Override + public String getEnvExecutables() + { + return System.getenv(PATHEXT); + } + +} diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java index f8876b2ba..6c4479a43 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/util/ToolsUtility.java @@ -27,13 +27,17 @@ import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.compress.utils.IOUtils; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.tukaani.xz.XZInputStream; import com.espressif.idf.core.IDFEnvironmentVariables; +import com.espressif.idf.core.SystemExecutableFinder; import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.tools.ToolsSystemWrapper; import com.espressif.idf.core.tools.vo.ToolsVO; import com.espressif.idf.core.util.FileUtil; +import com.espressif.idf.core.util.StringUtil; /** * Utility class for Tools Management operations @@ -303,4 +307,25 @@ public static String getFileChecksum(MessageDigest digest, File file) throws IOE } return sb.toString(); } + + /** + * Gets the absolute path for the tool from the given path + * @param toolName tool to find absolute path + * @param path the path to variable to look into, if null System.getenv() will be used + * @return absolute path to the tool + */ + public static IPath findAbsoluteToolPath(String toolName, String path) + { + if (StringUtil.isEmpty(path)) + { + Map env = System.getenv(); + if (env.containsKey(IDFEnvironmentVariables.PATH)) + path = env.get(IDFEnvironmentVariables.PATH); + else + path = env.get("Path"); //$NON-NLS-1$ + } + + SystemExecutableFinder systemExecutableFinder = new SystemExecutableFinder(new ToolsSystemWrapper(path)); + return systemExecutableFinder.find(toolName); + } } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java index 563231f40..92ab5bf9e 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/ToolsVO.java @@ -7,6 +7,7 @@ import java.text.DecimalFormat; import java.util.List; import java.util.Map; +import java.util.Objects; import org.eclipse.core.runtime.Platform; @@ -226,4 +227,33 @@ public void setVersionRegex(String versionRegex) { this.versionRegex = versionRegex; } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + ToolsVO other = (ToolsVO) obj; + return Objects.equals(description, other.description) + && Objects.equals(exportPaths, other.exportPaths) + && Objects.equals(exportVars, other.exportVars) + && Objects.equals(infoUrl, other.infoUrl) + && Objects.equals(installType, other.installType) + && Objects.equals(licesnse, other.licesnse) + && Objects.equals(name, other.name) + && Objects.equals(supportedTargets, other.supportedTargets) + && Objects.equals(versionCmd, other.versionCmd) + && Objects.equals(versionRegex, other.versionRegex) + && Objects.equals(versionVOs, other.versionVOs) + && Objects.equals(version, other.version) + && installed == other.installed; + } + + @Override + public int hashCode() + { + return Objects.hash(description, exportPaths, exportVars, infoUrl, installType, licesnse, name, supportedTargets, versionCmd, versionRegex, versionVOs, version, installed); + } } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java index 340c71d6b..a9a2122b0 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionDetailsVO.java @@ -5,6 +5,7 @@ package com.espressif.idf.core.tools.vo; import java.text.DecimalFormat; +import java.util.Objects; /** * Version details vo for the versions class @@ -70,4 +71,24 @@ public void setSelected(boolean selected) { this.selected = selected; } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + VersionDetailsVO other = (VersionDetailsVO) obj; + return Double.compare(size, other.size) == 0 + && selected == other.selected + && Objects.equals(sha256, other.sha256) + && Objects.equals(url, other.url); + } + + @Override + public int hashCode() + { + return Objects.hash(sha256, size, url, selected); + } } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java index 2441f8a7f..ac871a78a 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/tools/vo/VersionsVO.java @@ -5,6 +5,7 @@ package com.espressif.idf.core.tools.vo; import java.util.Map; +import java.util.Objects; /** * Versions class for versions information in tools json @@ -73,4 +74,25 @@ public void setAvailablePath(String availablePath) { this.availablePath = availablePath; } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + VersionsVO other = (VersionsVO) obj; + return isAvailable == other.isAvailable + && Objects.equals(name, other.name) + && Objects.equals(status, other.status) + && Objects.equals(versionOsMap, other.versionOsMap) + && Objects.equals(availablePath, other.availablePath); + } + + @Override + public int hashCode() + { + return Objects.hash(name, status, versionOsMap, isAvailable, availablePath); + } } diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java new file mode 100644 index 000000000..fd9e2aa3b --- /dev/null +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ +package com.espressif.idf.ui.dialogs; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.program.Program; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Shell; + +import com.espressif.idf.core.logging.Logger; + +/** + * URL Dialog class that can show multiple external web URLs in the text and + * make them click able and launches the default program to open them + * @author Ali Azam Rana + * + */ +public class URLDialog extends Dialog +{ + private static final String URL_REGEX = "\\b((http|https)://)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"; //$NON-NLS-1$ + + private String text; + private String title; + + public URLDialog(Shell parentShell, String title, String text) + { + super(parentShell); + this.text = text; + this.title = title; + } + + @Override + protected Control createDialogArea(Composite parent) + { + Composite container = new Composite((Composite) super.createDialogArea(parent), SWT.NONE); + container.setLayout(new GridLayout()); + Link link = new Link(container, SWT.NONE); + link.setText(getTextForLinkControl()); + link.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true)); + link.addListener(SWT.Selection, e -> Program.launch(e.text)); + return container; + } + + @Override + protected void configureShell(Shell newShell) + { + super.configureShell(newShell); + newShell.setText(title); + } + + private String getTextForLinkControl() + { + StringBuilder stringBuilder = new StringBuilder(); + Pattern pattern = Pattern.compile(URL_REGEX); + Matcher matcher = pattern.matcher(text); + int startIndex = 0, endIndex = text.length(); + while (matcher.find()) + { + String url = matcher.group(); + Logger.log("URL Found: " + url); + endIndex = text.indexOf(url); + stringBuilder.append(text.substring(startIndex, endIndex)); + stringBuilder.append(""); //$NON-NLS-1$ + stringBuilder.append(url); + stringBuilder.append(""); //$NON-NLS-1$ + startIndex = endIndex + url.length(); + endIndex = text.length(); + } + if (stringBuilder.toString().isEmpty()) + { + stringBuilder.append(text); + } + return stringBuilder.toString(); + } +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java index 2d40dd779..a2bf5e032 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/Messages.java @@ -105,6 +105,9 @@ public class Messages extends NLS public static String FilterTargetBoxToolTip; public static String ShowAvailableVersionsOnlyToolTip; public static String DeleteToolsTextToolTip; + public static String MissingToolsValidationMessage_A; + public static String MissingToolsValidationMessage_B; + public static String MissingToolsValidationLink; static { diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index 7b2f5b12f..d8141729a 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -26,9 +26,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.InstanceScope; @@ -50,6 +49,7 @@ import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; +import com.espressif.idf.ui.dialogs.URLDialog; import com.espressif.idf.ui.tools.wizard.pages.ManageToolsInstallationWizardPage; import com.espressif.idf.ui.update.InstallToolsHandler; @@ -585,9 +585,10 @@ public Boolean call() throws Exception private void validateToolsInstall() { + List missingToolsVOs = new ArrayList<>(); for (ToolsVO toolsVO : requireToolsVOs) { - final List arguments = new ArrayList(); + final List arguments = new ArrayList(); arguments.addAll(toolsVO.getVersionCmd()); final String cmd = Messages.AbstractToolsHandler_ExecutingMsg + " " + getCommandString(arguments); logQueue.add(cmd); @@ -602,13 +603,22 @@ else if (environment.containsKey("Path")) { environment.put("Path", idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH)); } + + IPath absolutePathToTool = ToolsUtility.findAbsoluteToolPath(toolsVO.getName(), + idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.PATH)); + if (absolutePathToTool == null) + { + Logger.log("Required tool: " + toolsVO.getName() + " not found on the PATH"); + missingToolsVOs.add(toolsVO); + continue; + } + arguments.add(0, absolutePathToTool.toOSString()); + arguments.remove(1); + final ProcessBuilderFactory processRunner = new ProcessBuilderFactory(); try { - final IStatus status = processRunner.runInBackground(arguments, - org.eclipse.core.runtime.Path.fromOSString( - idfEnvironmentVariables.getEnvValue(IDFEnvironmentVariables.IDF_PATH)), - environment); + final IStatus status = processRunner.runInBackground(arguments, null, environment); if (status == null) { Logger.log(IDFCorePlugin.getPlugin(), IDFCorePlugin.errorStatus("Status can't be null", null)); //$NON-NLS-1$ @@ -618,30 +628,31 @@ else if (environment.containsKey("Path")) final String cmdOutput = status.getMessage(); Logger.log(cmdOutput); logQueue.add(cmdOutput); - - Pattern pattern = Pattern.compile(toolsVO.getVersionRegex()); - Matcher matcher = pattern.matcher(cmdOutput); - if (matcher.find()) - { - String match = matcher.group(); - if (!match.equals(toolsVO.getVersion())) - { - Logger.log("Version Mismatch for " + toolsVO.getName() + " IDF required: " - + toolsVO.getVersion() + " Found: " + match); - logQueue.add("Version Mismatch for " + toolsVO.getName() + " IDF required: " - + toolsVO.getVersion() + " Found: " + match); - } - else - { - // TODO: Handle the case when the tool was not installed and is required - } - } } catch (IOException e1) { Logger.log(IDFCorePlugin.getPlugin(), e1); + missingToolsVOs.add(toolsVO); } } + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(Messages.MissingToolsValidationMessage_A); + stringBuilder.append(System.lineSeparator()); + for (ToolsVO toolsVO : missingToolsVOs) + { + stringBuilder.append(toolsVO.getName()); + stringBuilder.append(System.lineSeparator()); + } + + stringBuilder.append(Messages.MissingToolsValidationMessage_B); + stringBuilder.append(Messages.MissingToolsValidationLink); + + manageToolsInstallationWizardPage.getShell().getDisplay().asyncExec(() -> { + URLDialog urlDialog = new URLDialog(manageToolsInstallationWizardPage.getShell(), "Missing Tools", + stringBuilder.toString()); + urlDialog.open(); + }); } private void configEnv() @@ -773,16 +784,45 @@ private void replacePathVariable(StringBuilder paths) return; } - Map environment = System.getenv(); String systemPath = StringUtil.EMPTY; - if (environment.containsKey(IDFEnvironmentVariables.PATH)) + if (Platform.getOS().equals(Platform.OS_WIN32)) { - systemPath = environment.get(IDFEnvironmentVariables.PATH); + Map environment = System.getenv(); + + if (environment.containsKey(IDFEnvironmentVariables.PATH)) + { + systemPath = environment.get(IDFEnvironmentVariables.PATH); + } + else if (environment.containsKey("Path")) + { + systemPath = environment.get("Path"); + } } - else if (environment.containsKey("Path")) + else { - systemPath = environment.get("Path"); + try + { + ProcessBuilderFactory processBuilderFactory = new ProcessBuilderFactory(); + List arguments = new ArrayList<>(); + arguments.add("bash"); + arguments.add("-l"); + arguments.add("-c"); + arguments.add("echo $PATH"); + + IStatus status = processBuilderFactory.runInBackground(arguments, null, null); + if (status == null) + { + Logger.log(IDFCorePlugin.getPlugin(), IDFCorePlugin.errorStatus("Stat us can't be null", null)); //$NON-NLS-1$ + return; + } + + systemPath = status.getMessage(); + } + catch (IOException e) + { + e.printStackTrace(); + } } List pathsToAppend = new ArrayList(); diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties index 13273e708..bd697cd84 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties @@ -107,3 +107,6 @@ IDFDownloadWizard_DecompressingCompleted=Archive extracted! IDFDownloadWizard_UpdatingIDFPathMessage=Updating IDF_PATH to: {0} FilterTargetBoxToolTip=Filter the tools based on the target selection of ESP chips ShowAvailableVersionsOnlyToolTip=Shows the versions that are available already and downloaded. The versions should be in the espressif home directory to be visible with this. +MissingToolsValidationMessage_A=Following required tools are missing: +MissingToolsValidationMessage_B=Please visit the Link below to see configuration for these tools +MissingToolsValidationLink= diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java index e2e0b9c18..194a90a30 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java @@ -847,7 +847,6 @@ private void checkItems(TreeItem item, boolean checked) item.setChecked(checked); if (item.getParentItem() != null) { - String key = item.getText(0); VersionsVO versionsVO = (VersionsVO) item.getData(); for(String os : versionsVO.getVersionOsMap().keySet()) @@ -887,7 +886,7 @@ public void widgetSelected(SelectionEvent e) ManageToolsInstallationWizardPage.this, idfEnvironmentVariables); try { - toolsInstallationHandler.operationToPerform(selectedItems, forceDownloadBtn.getSelection(), + toolsInstallationHandler.operationToPerform(toolsJsonParser.getRequiredToolsList(), selectedItems, forceDownloadBtn.getSelection(), ToolsInstallationHandler.DELETING_TOOLS); } catch (Exception e1) From a1d1bb80824e04af5188220cdefe41f4aafd0746 Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:41:42 +0200 Subject: [PATCH 07/12] doc file and images for user guide added --- docs/MissingToolsManualPathUpdateGuide.md | 35 ++++++++++++++++++ docs/images/ToolsValidation/EnvSettings.png | Bin 0 -> 116461 bytes docs/images/ToolsValidation/PathVarEdit.png | Bin 0 -> 16416 bytes docs/images/ToolsValidation/PathVarEdited.png | Bin 0 -> 17565 bytes 4 files changed, 35 insertions(+) create mode 100644 docs/MissingToolsManualPathUpdateGuide.md create mode 100644 docs/images/ToolsValidation/EnvSettings.png create mode 100644 docs/images/ToolsValidation/PathVarEdit.png create mode 100644 docs/images/ToolsValidation/PathVarEdited.png diff --git a/docs/MissingToolsManualPathUpdateGuide.md b/docs/MissingToolsManualPathUpdateGuide.md new file mode 100644 index 000000000..52e8b36ab --- /dev/null +++ b/docs/MissingToolsManualPathUpdateGuide.md @@ -0,0 +1,35 @@ +# Installing Missing Tools and Updating Path + +Some tools are required as mandatory for the IDF and must be installed manually on Linux and MAC for windows the tools installation in the IDF-Eclipse Plugin takes care of them. Please vist [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html) link to first install them respective to your platform. + +Once you have installed the required tools you can move to the next step. +The `PATH` in the IDE is independent of the system's `PATH` variable so we need to configure it.
+ +We will be using CMake as an example but you need to make sure to follow the steps below for all the tools you have installed from the previous link. + +Run the following command to find out the install location of the tools + +For CMake `which cmake` This will output the path to the directory where the CMake is installed. If you dont get the path it could mean a trouble with the path in your terminal or installation please consult the documentation again for the installation and correct configuration of the PATH for your system. Your output may look something like this +
+`/opt/homebrew/bin/cmake` +
+We need to copy the path for the directory in which the CMake is present. So the path you will copy will look like this `/opt/homebrew/bin` +
+ +Once that is copied you can head over to the IDE. + +- Open Eclipse Settings and Go to `C/C++ -> Build -> Environment`. You will see these variables if you have installed the tools. +![](images/ToolsValidation/EnvSettings.png) + +
+ +- Select the `PATH` variable and click `Edit...`
+![](images/ToolsValidation/PathVarEdit.png) + +- Now paste the path that we previously copeid `/opt/homebrew/bin` at the start of the current path and place a colon `:` after that. Your original `PATH` value will always come after the path you have copied. It should look something like this.
+![](images/ToolsValidation/PathVarEdited.png) +
+ +Now as stated previously this was only for cmake you need to find the install locations of the other required tools and add them in the same way to the `PATH`. After you have done that you can click `OK` and then click `Apply and Close`. + +Once you have configured these correctly you should be able to build the projects. \ No newline at end of file diff --git a/docs/images/ToolsValidation/EnvSettings.png b/docs/images/ToolsValidation/EnvSettings.png new file mode 100644 index 0000000000000000000000000000000000000000..36d320a0fe074d8121a655bb4569b1b1921f4fa8 GIT binary patch literal 116461 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н) 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 kKcChAy51vU%%A3W-ZtN;K2 literal 0 HcmV?d00001 diff --git a/docs/images/ToolsValidation/PathVarEdit.png b/docs/images/ToolsValidation/PathVarEdit.png new file mode 100644 index 0000000000000000000000000000000000000000..7211fe937006bffc62136e1849f204c41d59ad15 GIT binary patch literal 16416 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

_kb2kziEUfH=_GMyK_j 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 N83}puZ=!}l{|D(9!(spc literal 0 HcmV?d00001 diff --git a/docs/images/ToolsValidation/PathVarEdited.png b/docs/images/ToolsValidation/PathVarEdited.png new file mode 100644 index 0000000000000000000000000000000000000000..55de6111273d02d346dbafb73bb81782adb20295 GIT binary patch literal 17565 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 Date: Wed, 26 Jul 2023 10:16:08 +0200 Subject: [PATCH 08/12] updated readme and some minor fixes --- .../ui/tools/ToolsInstallationHandler.java | 1 + .../idf/ui/tools/messages.properties | 2 +- docs/MissingToolsManualPathUpdateGuide.md | 21 ++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index d8141729a..448d6c0ac 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -646,6 +646,7 @@ else if (environment.containsKey("Path")) } stringBuilder.append(Messages.MissingToolsValidationMessage_B); + stringBuilder.append(System.lineSeparator()); stringBuilder.append(Messages.MissingToolsValidationLink); manageToolsInstallationWizardPage.getShell().getDisplay().asyncExec(() -> { diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties index bd697cd84..3ce48d71e 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties @@ -109,4 +109,4 @@ FilterTargetBoxToolTip=Filter the tools based on the target selection of ESP chi ShowAvailableVersionsOnlyToolTip=Shows the versions that are available already and downloaded. The versions should be in the espressif home directory to be visible with this. MissingToolsValidationMessage_A=Following required tools are missing: MissingToolsValidationMessage_B=Please visit the Link below to see configuration for these tools -MissingToolsValidationLink= +MissingToolsValidationLink=https://github.com/espressif/idf-eclipse-plugin/blob/master/docs/MissingToolsManualPathUpdateGuide.md diff --git a/docs/MissingToolsManualPathUpdateGuide.md b/docs/MissingToolsManualPathUpdateGuide.md index 52e8b36ab..f9384ecc5 100644 --- a/docs/MissingToolsManualPathUpdateGuide.md +++ b/docs/MissingToolsManualPathUpdateGuide.md @@ -1,15 +1,15 @@ # Installing Missing Tools and Updating Path -Some tools are required as mandatory for the IDF and must be installed manually on Linux and MAC for windows the tools installation in the IDF-Eclipse Plugin takes care of them. Please vist [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html) link to first install them respective to your platform. +Some tools are required as mandatory for the IDF and must be installed manually or must be selected when you are using the tools installation wizard on Linux and MAC and only selected recommended tools for windows these tools installation are mandatory and are selected with recommended tools. -Once you have installed the required tools you can move to the next step. -The `PATH` in the IDE is independent of the system's `PATH` variable so we need to configure it.
- -We will be using CMake as an example but you need to make sure to follow the steps below for all the tools you have installed from the previous link. +If you have these tools already present on your system you can skip the first step and continue from the second step. +1. In case you want to manually install these tools to the system first please vist [this](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/linux-macos-setup.html) link to install them respective to your platform. -Run the following command to find out the install location of the tools +*Once you have installed the required tools you can move to the next step. +The `PATH` in the IDE is independent of the system's `PATH` variable so we need to configure it.
* +*We will be using CMake as an example but you need to make sure to follow the steps below for all the tools you have installed from the previous link.* -For CMake `which cmake` This will output the path to the directory where the CMake is installed. If you dont get the path it could mean a trouble with the path in your terminal or installation please consult the documentation again for the installation and correct configuration of the PATH for your system. Your output may look something like this +2. Run the following command to find out the install location of the tools. For CMake `which cmake` This will output the path to the directory where the CMake is installed. If you dont get the path it could mean a trouble with the path in your terminal or installation please consult the documentation again for the installation and correct configuration of the PATH for your system. Your output may look something like this
`/opt/homebrew/bin/cmake`
@@ -18,18 +18,19 @@ We need to copy the path for the directory in which the CMake is present. So the Once that is copied you can head over to the IDE. -- Open Eclipse Settings and Go to `C/C++ -> Build -> Environment`. You will see these variables if you have installed the tools. +3. Open Settings and Go to `C/C++ -> Build -> Environment`. You will see these variables if you have installed the tools. ![](images/ToolsValidation/EnvSettings.png)
-- Select the `PATH` variable and click `Edit...`
+4. Select the `PATH` variable and click `Edit...`
![](images/ToolsValidation/PathVarEdit.png) -- Now paste the path that we previously copeid `/opt/homebrew/bin` at the start of the current path and place a colon `:` after that. Your original `PATH` value will always come after the path you have copied. It should look something like this.
+5. Now paste the path that we previously copeid `/opt/homebrew/bin` at the start of the current path and place a colon `:` after that. Your original `PATH` value will always come after the path you have copied. It should look something like this.
![](images/ToolsValidation/PathVarEdited.png)
+ Now as stated previously this was only for cmake you need to find the install locations of the other required tools and add them in the same way to the `PATH`. After you have done that you can click `OK` and then click `Apply and Close`. Once you have configured these correctly you should be able to build the projects. \ No newline at end of file From b9c4271080258b8390ae78c932ff6b1bda24934b Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Thu, 27 Jul 2023 14:38:04 +0200 Subject: [PATCH 09/12] updated ui as per discussion --- .../espressif/idf/ui/dialogs/URLDialog.java | 85 ------------------- .../ui/tools/ToolsInstallationHandler.java | 14 +-- .../idf/ui/tools/messages.properties | 2 +- .../ManageToolsInstallationWizardPage.java | 17 ++++ 4 files changed, 25 insertions(+), 93 deletions(-) delete mode 100644 bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java deleted file mode 100644 index fd9e2aa3b..000000000 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/dialogs/URLDialog.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright 2023 Espressif Systems (Shanghai) PTE LTD. All rights reserved. - * Use is subject to license terms. - *******************************************************************************/ -package com.espressif.idf.ui.dialogs; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.program.Program; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Link; -import org.eclipse.swt.widgets.Shell; - -import com.espressif.idf.core.logging.Logger; - -/** - * URL Dialog class that can show multiple external web URLs in the text and - * make them click able and launches the default program to open them - * @author Ali Azam Rana - * - */ -public class URLDialog extends Dialog -{ - private static final String URL_REGEX = "\\b((http|https)://)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"; //$NON-NLS-1$ - - private String text; - private String title; - - public URLDialog(Shell parentShell, String title, String text) - { - super(parentShell); - this.text = text; - this.title = title; - } - - @Override - protected Control createDialogArea(Composite parent) - { - Composite container = new Composite((Composite) super.createDialogArea(parent), SWT.NONE); - container.setLayout(new GridLayout()); - Link link = new Link(container, SWT.NONE); - link.setText(getTextForLinkControl()); - link.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true)); - link.addListener(SWT.Selection, e -> Program.launch(e.text)); - return container; - } - - @Override - protected void configureShell(Shell newShell) - { - super.configureShell(newShell); - newShell.setText(title); - } - - private String getTextForLinkControl() - { - StringBuilder stringBuilder = new StringBuilder(); - Pattern pattern = Pattern.compile(URL_REGEX); - Matcher matcher = pattern.matcher(text); - int startIndex = 0, endIndex = text.length(); - while (matcher.find()) - { - String url = matcher.group(); - Logger.log("URL Found: " + url); - endIndex = text.indexOf(url); - stringBuilder.append(text.substring(startIndex, endIndex)); - stringBuilder.append(""); //$NON-NLS-1$ - stringBuilder.append(url); - stringBuilder.append(""); //$NON-NLS-1$ - startIndex = endIndex + url.length(); - endIndex = text.length(); - } - if (stringBuilder.toString().isEmpty()) - { - stringBuilder.append(text); - } - return stringBuilder.toString(); - } -} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index 448d6c0ac..8547327ca 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -49,7 +49,6 @@ import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.StringUtil; import com.espressif.idf.ui.UIPlugin; -import com.espressif.idf.ui.dialogs.URLDialog; import com.espressif.idf.ui.tools.wizard.pages.ManageToolsInstallationWizardPage; import com.espressif.idf.ui.update.InstallToolsHandler; @@ -638,21 +637,22 @@ else if (environment.containsKey("Path")) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(Messages.MissingToolsValidationMessage_A); - stringBuilder.append(System.lineSeparator()); for (ToolsVO toolsVO : missingToolsVOs) { stringBuilder.append(toolsVO.getName()); - stringBuilder.append(System.lineSeparator()); + stringBuilder.append(" "); } stringBuilder.append(Messages.MissingToolsValidationMessage_B); - stringBuilder.append(System.lineSeparator()); + stringBuilder.append(""); stringBuilder.append(Messages.MissingToolsValidationLink); + stringBuilder.append(""); + + logQueue.add(stringBuilder.toString()); manageToolsInstallationWizardPage.getShell().getDisplay().asyncExec(() -> { - URLDialog urlDialog = new URLDialog(manageToolsInstallationWizardPage.getShell(), "Missing Tools", - stringBuilder.toString()); - urlDialog.open(); + manageToolsInstallationWizardPage.getLinkForDoc().setText(stringBuilder.toString()); + manageToolsInstallationWizardPage.getLinkForDoc().setVisible(true); }); } diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties index 3ce48d71e..017182328 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/messages.properties @@ -108,5 +108,5 @@ IDFDownloadWizard_UpdatingIDFPathMessage=Updating IDF_PATH to: {0} FilterTargetBoxToolTip=Filter the tools based on the target selection of ESP chips ShowAvailableVersionsOnlyToolTip=Shows the versions that are available already and downloaded. The versions should be in the espressif home directory to be visible with this. MissingToolsValidationMessage_A=Following required tools are missing: -MissingToolsValidationMessage_B=Please visit the Link below to see configuration for these tools +MissingToolsValidationMessage_B=Please visit the Link to see configuration for these tools MissingToolsValidationLink=https://github.com/espressif/idf-eclipse-plugin/blob/master/docs/MissingToolsManualPathUpdateGuide.md diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java index 194a90a30..fff211bbb 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/wizard/pages/ManageToolsInstallationWizardPage.java @@ -28,11 +28,13 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.ProgressBar; @@ -110,6 +112,7 @@ public class ManageToolsInstallationWizardPage extends WizardPage implements ITo private Preferences scopedPreferenceStore; private Button forceDownloadBtn; private Listener[] listenersForFinish; + private Link linkForDoc; public ManageToolsInstallationWizardPage(WizardDialog parentWizardDialog, ToolsJsonParser toolsJsonParser) { @@ -270,6 +273,10 @@ public void widgetSelected(SelectionEvent e) progressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); progressBar.setVisible(false); + linkForDoc = new Link(logAreaComposite, SWT.WRAP | SWT.MULTI); + linkForDoc.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 3)); + linkForDoc.addListener(SWT.Selection, e -> Program.launch(e.text)); + linkForDoc.setVisible(false); createButtonsBar(logAreaComposite); setButtonsEnabled(itemChecked); @@ -942,6 +949,16 @@ public void afterDeleteToolMessage() } } + public Link getLinkForDoc() + { + return linkForDoc; + } + + public void setLinkForDoc(Link linkForDoc) + { + this.linkForDoc = linkForDoc; + } + private class SelectRecommendedButtonSelectionAdapter extends SelectionAdapter { @Override From 25868db1e0b8a1e7dc7fb641d9a869744599c5d5 Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Thu, 14 Sep 2023 10:45:46 +0200 Subject: [PATCH 10/12] fix(installation): Grant file permission before executable verification --- .../idf/core/SystemExecutableFinder.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemExecutableFinder.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemExecutableFinder.java index cda63ef63..9d927c859 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemExecutableFinder.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/SystemExecutableFinder.java @@ -5,11 +5,13 @@ package com.espressif.idf.core; import java.io.File; +import java.io.IOException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; +import com.espressif.idf.core.logging.Logger; import com.espressif.idf.core.util.StringUtil; public class SystemExecutableFinder implements ExecutableFinder @@ -79,9 +81,21 @@ private IPath findExecutable(IPath path) } } - else if (isExecutable(path)) + else { - return path; + try + { + Runtime.getRuntime().exec("/bin/chmod 755 ".concat(path.toOSString())); //$NON-NLS-1$ + } + catch (IOException e) + { + Logger.log(e); + } + + if (isExecutable(path)) + { + return path; + } } return null; } @@ -100,7 +114,7 @@ private boolean isExecutable(IPath path) { return false; } - + return file.canExecute(); } } From 116cc9f1478bdc6fa6a69ccb78e1d6c5d75d9aae Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:02:44 +0200 Subject: [PATCH 11/12] fix(pom.xml): updated the version for the commons-io in core project pom file --- bundles/com.espressif.idf.core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/com.espressif.idf.core/pom.xml b/bundles/com.espressif.idf.core/pom.xml index 2b2f0dd8b..331b67819 100644 --- a/bundles/com.espressif.idf.core/pom.xml +++ b/bundles/com.espressif.idf.core/pom.xml @@ -21,7 +21,7 @@ commons-io commons-io - 2.10.0 + 2.13.0 From 5ce61a2369862fdc3dc0ee8dd380c27a316b82d1 Mon Sep 17 00:00:00 2001 From: Ali Azam Rana <85216275+alirana01@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:26:56 +0200 Subject: [PATCH 12/12] fix(installation): empty message fix if no missing tools are found --- .../com/espressif/idf/ui/tools/ToolsInstallationHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java index 8547327ca..f5e24de5e 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsInstallationHandler.java @@ -635,6 +635,9 @@ else if (environment.containsKey("Path")) } } + if (missingToolsVOs.isEmpty()) + return; + StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(Messages.MissingToolsValidationMessage_A); for (ToolsVO toolsVO : missingToolsVOs)