diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 8ae5c6554..dbc20a2dc 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -8,6 +8,7 @@ Release with new features and bugfixes: * https://github.com/devonfw/IDEasy/issues/757[#757]: Support to allow settings in code repository * https://github.com/devonfw/IDEasy/issues/826[#826]: Fix git settings check when settings folder is empty +* https://github.com/devonfw/IDEasy/issues/894[#894]: Fix ide.bat printing for initialization and error output The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/18?closed=1[milestone 2025.01.001]. diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java index d3f46e900..a9636c2e3 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java +++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java @@ -257,18 +257,29 @@ default void extract(Path archiveFile, Path targetDir, Consumer postExtrac boolean isEmptyDir(Path dir); /** - * Makes a file executable. Equivalent of using 'chmod a+x'. Adds execute permissions to current file permissions. + * Makes a file executable (analog to 'chmod a+x'). * - * @param filePath {@link Path} to the file. + * @param file {@link Path} to the file. */ - void makeExecutable(Path filePath); + default void makeExecutable(Path file) { + + makeExecutable(file, false); + } + + /** + * Makes a file executable (analog to 'chmod a+x'). + * + * @param file {@link Path} to the file. + * @param confirm - {@code true} to get user confirmation before adding missing executable flags, {@code false} otherwise (always set missing flags). + */ + void makeExecutable(Path file, boolean confirm); /** * Like the linux touch command this method will update the modification time of the given {@link Path} to the current * {@link System#currentTimeMillis() system time}. In case the file does not exist, it will be created as empty file. If already the * {@link Path#getParent() parent folder} does not exist, the operation will fail. * - * @param filePath the {@link Path} to the file or folder. + * @param file the {@link Path} to the file or folder. */ - void touch(Path filePath); + void touch(Path file); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java index 87a3896f3..ae2f0b605 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java @@ -27,6 +27,7 @@ import java.security.NoSuchAlgorithmException; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -903,52 +904,67 @@ public Path findExistingFile(String fileName, List searchDirs) { } @Override - public void makeExecutable(Path filePath) { + public void makeExecutable(Path file, boolean confirm) { - if (Files.exists(filePath)) { + if (Files.exists(file)) { if (SystemInfoImpl.INSTANCE.isWindows()) { - this.context.trace("Windows does not have executable flags hence omitting for file {}", filePath); + this.context.trace("Windows does not have executable flags hence omitting for file {}", file); return; } try { // Read the current file permissions - Set perms = Files.getPosixFilePermissions(filePath); + Set existingPermissions = Files.getPosixFilePermissions(file); // Add execute permission for all users + Set executablePermissions = new HashSet<>(existingPermissions); boolean update = false; - update |= perms.add(PosixFilePermission.OWNER_EXECUTE); - update |= perms.add(PosixFilePermission.GROUP_EXECUTE); - update |= perms.add(PosixFilePermission.OTHERS_EXECUTE); + update |= executablePermissions.add(PosixFilePermission.OWNER_EXECUTE); + update |= executablePermissions.add(PosixFilePermission.GROUP_EXECUTE); + update |= executablePermissions.add(PosixFilePermission.OTHERS_EXECUTE); if (update) { - this.context.debug("Setting executable flags for file {}", filePath); + if (confirm) { + boolean yesContinue = this.context.question( + "We want to execute " + file.getFileName() + " but this command seems to lack executable permissions!\n" + + "Most probably the tool vendor did forgot to add x-flags in the binary release package.\n" + + "Before running the command, we suggest to set executable permissions to the file:\n" + + file + "\n" + + "For security reasons we ask for your confirmation so please check this request.\n" + + "Changing permissions from " + PosixFilePermissions.toString(existingPermissions) + " to " + PosixFilePermissions.toString( + executablePermissions) + ".\n" + + "Do you confirm to make the command executable before running it?"); + if (!yesContinue) { + return; + } + } + this.context.debug("Setting executable flags for file {}", file); // Set the new permissions - Files.setPosixFilePermissions(filePath, perms); + Files.setPosixFilePermissions(file, executablePermissions); } else { - this.context.trace("Executable flags already present so no need to set them for file {}", filePath); + this.context.trace("Executable flags already present so no need to set them for file {}", file); } } catch (IOException e) { throw new RuntimeException(e); } } else { - this.context.warning("Cannot set executable flag on file that does not exist: {}", filePath); + this.context.warning("Cannot set executable flag on file that does not exist: {}", file); } } @Override - public void touch(Path filePath) { + public void touch(Path file) { - if (Files.exists(filePath)) { + if (Files.exists(file)) { try { - Files.setLastModifiedTime(filePath, FileTime.fromMillis(System.currentTimeMillis())); + Files.setLastModifiedTime(file, FileTime.fromMillis(System.currentTimeMillis())); } catch (IOException e) { - throw new IllegalStateException("Could not update modification-time of " + filePath, e); + throw new IllegalStateException("Could not update modification-time of " + file, e); } } else { try { - Files.createFile(filePath); + Files.createFile(file); } catch (IOException e) { - throw new IllegalStateException("Could not create empty file " + filePath, e); + throw new IllegalStateException("Could not create empty file " + file, e); } } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java index 3290b8cf0..e9d1a8c71 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java @@ -150,7 +150,7 @@ public ProcessResult run(ProcessMode processMode) { this.executable = systemPath.findBinary(this.executable); this.processBuilder.environment().put(IdeVariables.PATH.getName(), path); List args = new ArrayList<>(this.arguments.size() + 4); - String interpreter = addExecutable(this.executable.toString(), args); + String interpreter = addExecutable(args); args.addAll(this.arguments); String command = createCommand(); if (this.context.debug().isEnabled()) { @@ -297,11 +297,12 @@ private String getSheBang(Path file) { return null; } - private String addExecutable(String exec, List args) { + private String addExecutable(List args) { String interpreter = null; - String fileExtension = FilenameUtil.getExtension(exec); + String fileExtension = FilenameUtil.getExtension(this.executable.getFileName().toString()); boolean isBashScript = "sh".equals(fileExtension); + this.context.getFileAccess().makeExecutable(this.executable, true); if (!isBashScript) { String sheBang = getSheBang(this.executable); if (sheBang != null) { @@ -325,7 +326,7 @@ private String addExecutable(String exec, List args) { args.add(0, "/i"); args.add(0, "msiexec"); } - args.add(exec); + args.add(this.executable.toString()); return interpreter; } diff --git a/cli/src/main/package/bin/ide.bat b/cli/src/main/package/bin/ide.bat index 6f0bdec0c..b3e8e0a33 100644 --- a/cli/src/main/package/bin/ide.bat +++ b/cli/src/main/package/bin/ide.bat @@ -21,10 +21,7 @@ if exist "%GIT_CORE%" ( if not "%1%" == "" ( ideasy %IDE_OPTIONS% %* - if not %ERRORLEVEL% == 0 ( - echo %_fBRed%Error: IDEasy failed with exit code %ERRORLEVEL% %_RESET% - exit /b %ERRORLEVEL% - ) + goto :output_error ) REM https://stackoverflow.com/questions/61888625/what-is-f-in-the-for-loop-command @@ -32,6 +29,14 @@ for /f "tokens=*" %%i in ('ideasy %IDE_OPTIONS% env') do ( call set %%i ) -if not %ERRORLEVEL% == 0 ( +ideasy %IDE_OPTIONS% env>nul + +if %ERRORLEVEL% == 0 ( echo IDE environment variables have been set for %IDE_HOME% in workspace %WORKSPACE% ) + +:output_error +if not %ERRORLEVEL% == 0 ( + echo %_fBRed%Error: IDEasy failed with exit code %ERRORLEVEL% %_RESET% + exit /b %ERRORLEVEL% +) diff --git a/cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn b/cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/gradle/gradle/default/bin/gradle b/cli/src/test/resources/ide-projects/build/repository/gradle/gradle/default/bin/gradle old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/java/java/default/bin/java b/cli/src/test/resources/ide-projects/build/repository/java/java/default/bin/java old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/mvn/mvn/default/bin/mvn b/cli/src/test/resources/ide-projects/build/repository/mvn/mvn/default/bin/mvn old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/node/node/default/node_modules/npm/bin/npm b/cli/src/test/resources/ide-projects/build/repository/node/node/default/node_modules/npm/bin/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/node/node/default/node_modules/npm/bin/npx b/cli/src/test/resources/ide-projects/build/repository/node/node/default/node_modules/npm/bin/npx old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/build/repository/npm/npm/default/bin/npm b/cli/src/test/resources/ide-projects/build/repository/npm/npm/default/bin/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/dotnet/repository/dotnet/dotnet/default/linux/dotnet b/cli/src/test/resources/ide-projects/dotnet/repository/dotnet/dotnet/default/linux/dotnet old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/dotnet/repository/dotnet/dotnet/default/mac/dotnet b/cli/src/test/resources/ide-projects/dotnet/repository/dotnet/dotnet/default/mac/dotnet old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/linux/eclipse b/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/linux/eclipse old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/mac/Eclipse.app/Contents/MacOS/eclipse b/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/mac/Eclipse.app/Contents/MacOS/eclipse old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/windows/eclipse b/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/windows/eclipse old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/windows/eclipsec b/cli/src/test/resources/ide-projects/eclipse/repository/eclipse/eclipse/default/windows/eclipsec old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/eclipse/repository/java/java/default/bin/java b/cli/src/test/resources/ide-projects/eclipse/repository/java/java/default/bin/java old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/intellij/repository/java/java/default/bin/java b/cli/src/test/resources/ide-projects/intellij/repository/java/java/default/bin/java old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/jasypt/repository/java/java/default/bin/java b/cli/src/test/resources/ide-projects/jasypt/repository/java/java/default/bin/java old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/jmc/repository/jmc/jmc/default/windows/JDK Mission Control/jmc b/cli/src/test/resources/ide-projects/jmc/repository/jmc/jmc/default/windows/JDK Mission Control/jmc old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/mvn/repository/mvn/mvn/default/bin/mvn b/cli/src/test/resources/ide-projects/mvn/repository/mvn/mvn/default/bin/mvn old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/npm/repository/node/node/default/npm b/cli/src/test/resources/ide-projects/npm/repository/node/node/default/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/npm/repository/node/node/default/npx b/cli/src/test/resources/ide-projects/npm/repository/node/node/default/npx old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/linux/bin/npm b/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/linux/bin/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/mac/bin/npm b/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/mac/bin/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/windows/bin/npm b/cli/src/test/resources/ide-projects/npm/repository/npm/npm/default/windows/bin/npm old mode 100644 new mode 100755 diff --git a/cli/src/test/resources/ide-projects/vscode/repository/vscode/vscode/default/bin/code b/cli/src/test/resources/ide-projects/vscode/repository/vscode/vscode/default/bin/code old mode 100644 new mode 100755 diff --git a/documentation/advanced-tooling-generic.adoc b/documentation/advanced-tooling-generic.adoc index 9ea867fd1..b96dc5347 100644 --- a/documentation/advanced-tooling-generic.adoc +++ b/documentation/advanced-tooling-generic.adoc @@ -6,7 +6,13 @@ toc::[] == Browser Plugins There are tons of helpful browser plugins out there and it might be a matter of personal taste what you like to have installed. -However, as we are heavily using github we want to promote https://github.com/buunguyen/octotree#octotree[octotree]. +The following are explicitly worth to mention: + +* https://darkreader.org/[DarkReader] - for developers enjoying dark-mode (and get eye-cancer from white backgrounds) +* https://www.tampermonkey.net/[TamperMonkey] - even though not recommended to be always on for security reasons this is the ultimate swiss-army-knife of every web-developer. +* FF only: https://addons.mozilla.org/en-US/firefox/addon/simple-tab-groups/[Simple Tab Groups] - only for power-users that need to manage 100+ open tabs in multi-tenancy contexts (project A, project B, timetracking, travel, etc.). + +For the record: HttpsEverywhere is dead since now there is https://www.eff.org/https-everywhere/set-https-default-your-browser[native browser support for HTTPS only]. == Draw Diagrams @@ -21,7 +27,3 @@ Its simplicity allows branching and merging unlike other greedy binary UML data- If you are looking for a git client that works cross-platform we recommend to use https://git-fork.com/[Fork]. -== Tab Grouping For The Web Browser - -https://addons.mozilla.org/en-US/firefox/addon/simple-tab-groups/[Simple Tab Groups] is a Firefox plugin that helps to separate tabs e.g. tabs for projekt A, projekt B, travelplanning or hobbies -