Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#881: add self healing feature to add x-flags before running command #904

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,18 +257,29 @@ default void extract(Path archiveFile, Path targetDir, Consumer<Path> 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);
}
40 changes: 26 additions & 14 deletions cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -903,16 +903,16 @@ public Path findExistingFile(String fileName, List<Path> 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<PosixFilePermission> perms = Files.getPosixFilePermissions(filePath);
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file);

// Add execute permission for all users
boolean update = false;
Expand All @@ -921,34 +921,46 @@ public void makeExecutable(Path filePath) {
update |= perms.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"
+ "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, perms);
} 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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public ProcessResult run(ProcessMode processMode) {
this.executable = systemPath.findBinary(this.executable);
this.processBuilder.environment().put(IdeVariables.PATH.getName(), path);
List<String> 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()) {
Expand Down Expand Up @@ -297,11 +297,12 @@ private String getSheBang(Path file) {
return null;
}

private String addExecutable(String exec, List<String> args) {
private String addExecutable(List<String> 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) {
Expand All @@ -325,7 +326,7 @@ private String addExecutable(String exec, List<String> args) {
args.add(0, "/i");
args.add(0, "msiexec");
}
args.add(exec);
args.add(this.executable.toString());
return interpreter;
}

Expand Down
Loading