Skip to content

Commit

Permalink
Merge branch 'main' into feature/devonfw#103-implement-version-securi…
Browse files Browse the repository at this point in the history
…ty-checks
  • Loading branch information
jan-vcapgemini committed Feb 29, 2024
2 parents 4d6766c + 9d89b23 commit f162e09
Show file tree
Hide file tree
Showing 15 changed files with 894 additions and 164 deletions.
2 changes: 1 addition & 1 deletion cli/src/main/java/com/devonfw/tools/ide/cli/Ideasy.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private AbstractIdeContext initContext(CliArguments arguments) {
if (property instanceof FlagProperty) {
((FlagProperty) property).setValue(Boolean.TRUE);
} else {
this.context.error("Missing value for option {}", key);
System.err.println("Missing value for option " + key);
}
} else {
property.setValueAsString(value, this.context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ public Path findBinary(Path toolPath) {
String fileName = toolPath.getFileName().toString();

if (parent == null) {

for (Path path : tool2pathMap.values()) {
Path binaryPath = findBinaryInOrder(path, fileName);
if (binaryPath != null) {
return binaryPath;
}
}

for (Path path : this.paths) {
Path binaryPath = findBinaryInOrder(path, fileName);
if (binaryPath != null) {
Expand Down
124 changes: 13 additions & 111 deletions cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.time.Duration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -39,7 +37,6 @@
import com.devonfw.tools.ide.os.SystemInfoImpl;
import com.devonfw.tools.ide.process.ProcessContext;
import com.devonfw.tools.ide.process.ProcessContextImpl;
import com.devonfw.tools.ide.process.ProcessErrorHandling;
import com.devonfw.tools.ide.process.ProcessResult;
import com.devonfw.tools.ide.property.Property;
import com.devonfw.tools.ide.repo.CustomToolRepository;
Expand All @@ -54,6 +51,8 @@
*/
public abstract class AbstractIdeContext implements IdeContext {

private static final String IDE_URLS_GIT = "https://github.com/devonfw/ide-urls.git";

private final Map<IdeLogLevel, IdeSubLogger> loggers;

private final Path ideHome;
Expand Down Expand Up @@ -120,8 +119,6 @@ public abstract class AbstractIdeContext implements IdeContext {

private UrlMetadata urlMetadata;

private static final Duration GIT_PULL_CACHE_DELAY_MILLIS = Duration.ofMillis(30 * 60 * 1000);

/**
* The constructor.
*
Expand Down Expand Up @@ -186,10 +183,11 @@ public AbstractIdeContext(IdeLogLevel minLogLevel, Function<IdeLogLevel, IdeSubL
Path rootPath = Path.of(root);
if (Files.isDirectory(rootPath)) {
if (!ideRootPath.equals(rootPath)) {
warning("Variable IDE_ROOT is set to '{}' but for your project '{}' would have been expected.");
ideRootPath = rootPath;
warning(
"Variable IDE_ROOT is set to '{}' but for your project '{}' the path '{}' would have been expected.",
root, this.ideHome.getFileName(), ideRootPath);
}
ideRootPath = this.ideHome.getParent();
ideRootPath = rootPath;
} else {
warning("Variable IDE_ROOT is not set to a valid directory '{}'." + root);
ideRootPath = null;
Expand Down Expand Up @@ -266,10 +264,7 @@ public String getMessageIdeHome() {
*/
public boolean isTest() {

if (isMock()) {
return true;
}
return false;
return isMock();
}

/**
Expand Down Expand Up @@ -496,7 +491,7 @@ public UrlMetadata getUrls() {

if (this.urlMetadata == null) {
if (!isTest()) {
gitPullOrCloneIfNeeded(this.urlsPath, "https://github.com/devonfw/ide-urls.git");
this.getGitContext().pullOrFetchAndResetIfNeeded(IDE_URLS_GIT, this.urlsPath, "origin", "master");
}
this.urlMetadata = new UrlMetadata(this);
}
Expand Down Expand Up @@ -566,7 +561,7 @@ public boolean isOnline() {
try {
int timeout = 1000;
online = InetAddress.getByName("github.com").isReachable(timeout);
} catch (Exception e) {
} catch (Exception ignored) {

}
return online;
Expand Down Expand Up @@ -596,108 +591,15 @@ public DirectoryMerger getWorkspaceMerger() {
}

@Override
public ProcessContext newProcess() {
public GitContext getGitContext() {

ProcessContext processContext = new ProcessContextImpl(this);
return processContext;
return new GitContextImpl(this);
}

@Override
public void gitPullOrClone(Path target, String gitRepoUrl) {

Objects.requireNonNull(target);
Objects.requireNonNull(gitRepoUrl);
if (!gitRepoUrl.startsWith("http")) {
throw new IllegalArgumentException("Invalid git URL '" + gitRepoUrl + "'!");
}
ProcessContext pc = newProcess().directory(target).executable("git").withEnvVar("GIT_TERMINAL_PROMPT", "0");
if (Files.isDirectory(target.resolve(".git"))) {
ProcessResult result = pc.addArg("remote").run(true, false);
List<String> remotes = result.getOut();
if (remotes.isEmpty()) {
String message = "This is a local git repo with no remote - if you did this for testing, you may continue...\n"
+ "Do you want to ignore the problem and continue anyhow?";
askToContinue(message);
} else {
pc.errorHandling(ProcessErrorHandling.WARNING);
result = pc.addArg("pull").run(false, false);
if (!result.isSuccessful()) {
String message = "Failed to update git repository at " + target;
if (this.offlineMode) {
warning(message);
interaction("Continuing as we are in offline mode - results may be outdated!");
} else {
error(message);
if (isOnline()) {
error("See above error for details. If you have local changes, please stash or revert and retry.");
} else {
error(
"It seems you are offline - please ensure Internet connectivity and retry or activate offline mode (-o or --offline).");
}
askToContinue("Typically you should abort and fix the problem. Do you want to continue anyways?");
}
}
}
} else {
String branch = null;
int hashIndex = gitRepoUrl.indexOf("#");
if (hashIndex != -1) {
branch = gitRepoUrl.substring(hashIndex + 1);
gitRepoUrl = gitRepoUrl.substring(0, hashIndex);
}
this.fileAccess.mkdirs(target);
requireOnline("git clone of " + gitRepoUrl);
pc.addArg("clone");
if (isQuietMode()) {
pc.addArg("-q");
} else {
}
pc.addArgs("--recursive", gitRepoUrl, "--config", "core.autocrlf=false", ".");
pc.run();
if (branch != null) {
pc.addArgs("checkout", branch);
pc.run();
}
}
}

/**
* Checks if the Git repository in the specified target folder needs an update by inspecting the modification time of
* a magic file.
*
* @param urlsPath The Path to the Urls repository.
* @param repoUrl The git remote URL of the Urls repository.
*/

private void gitPullOrCloneIfNeeded(Path urlsPath, String repoUrl) {

Path gitDirectory = urlsPath.resolve(".git");

// Check if the .git directory exists
if (Files.isDirectory(gitDirectory)) {
Path magicFilePath = gitDirectory.resolve("HEAD");
long currentTime = System.currentTimeMillis();
// Get the modification time of the magic file
long fileMTime;
try {
fileMTime = Files.getLastModifiedTime(magicFilePath).toMillis();
} catch (IOException e) {
throw new IllegalStateException("Could not read " + magicFilePath, e);
}
public ProcessContext newProcess() {

// Check if the file modification time is older than the delta threshold
if ((currentTime - fileMTime > GIT_PULL_CACHE_DELAY_MILLIS.toMillis()) || isForceMode()) {
gitPullOrClone(urlsPath, repoUrl);
try {
Files.setLastModifiedTime(magicFilePath, FileTime.fromMillis(currentTime));
} catch (IOException e) {
throw new IllegalStateException("Could not read or write in " + magicFilePath, e);
}
}
} else {
// If the .git directory does not exist, perform git clone
gitPullOrClone(urlsPath, repoUrl);
}
return new ProcessContextImpl(this);
}

@Override
Expand Down
87 changes: 87 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/context/GitContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.devonfw.tools.ide.context;

import java.nio.file.Path;

import com.devonfw.tools.ide.log.IdeLogger;

/**
* Interface for git commands with input and output of information for the user.
*/
public interface GitContext extends IdeLogger {

/**
* Checks if the Git repository in the specified target folder needs an update by inspecting the modification time of
* a magic file.
*
* @param repoUrl the git remote URL to clone from. May be suffixed with a hash-sign ('#') followed by the branch name
* to check-out.
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
*/
void pullOrCloneIfNeeded(String repoUrl, Path targetRepository);

/**
* Attempts a git pull and reset if required.
*
* @param repoUrl the git remote URL to clone from. May be suffixed with a hash-sign ('#') followed by the branch name
* to check-out.
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
* @param remoteName the remote name e.g. origin.
* @param branchName the branch name e.g. master.
*/
void pullOrFetchAndResetIfNeeded(String repoUrl, Path targetRepository, String remoteName, String branchName);

/**
* Runs a git pull or a git clone.
*
* @param gitRepoUrl the git remote URL to clone from. May be suffixed with a hash-sign ('#') followed by the branch
* name to check-out.
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
*/
void pullOrClone(String gitRepoUrl, Path targetRepository);

/**
* Runs a git clone. Throws a CliException if in offline mode.
*
* @param gitRepoUrl the {@link GitUrl} to use for the repository URL.
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
*/
void clone(GitUrl gitRepoUrl, Path targetRepository);

/**
* Runs a git pull.
*
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
*/
void pull(Path targetRepository);

/**
* Runs a git reset if files were modified.
*
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
* @param remoteName the remote server name.
* @param branchName the name of the branch.
*/
void reset(Path targetRepository, String remoteName, String branchName);

/**
* Runs a git cleanup if untracked files were found.
*
* @param targetRepository the {@link Path} to the target folder where the git repository should be cloned or pulled.
* It is not the parent directory where git will by default create a sub-folder by default on clone but the *
* final folder that will contain the ".git" subfolder.
*/
void cleanup(Path targetRepository);

}
Loading

0 comments on commit f162e09

Please sign in to comment.