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

#312: Added ability to prefer git (ssh) protocol instead of https for cloning repos #724

Merged
merged 39 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1c3750b
added git url enum GitUrlSyntax.java for ssh and https urls, modified…
diiinesh Sep 17, 2024
73805f7
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Sep 17, 2024
69d70fd
Update cli/src/main/java/com/devonfw/tools/ide/context/GitUrl.java
diiinesh Sep 18, 2024
c8a4778
Update cli/src/test/java/com/devonfw/tools/ide/context/GitContextTest…
diiinesh Sep 18, 2024
21ddcf2
modifed enum to not take strings as inputs, added VariableDefinitionE…
diiinesh Oct 1, 2024
a2dc43d
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Oct 1, 2024
c4e38b8
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Oct 1, 2024
dec7402
added PREFERRED_GIT_PROTOCOL property to assert ide properties file
diiinesh Oct 1, 2024
89e1b02
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Oct 1, 2024
1c5dc97
removed property from basic project config file and created new test …
diiinesh Oct 1, 2024
cb2dd52
Merge remote-tracking branch 'origin/Enhancement/git_ssh_protocol' in…
diiinesh Oct 1, 2024
d7807ed
changed test context from basic to git, and added some java docs
diiinesh Oct 1, 2024
98c11d0
changed test context from basic to git, and added some java docs
diiinesh Oct 1, 2024
b6f18bc
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Oct 1, 2024
00c2bec
logging for git action build error
diiinesh Oct 1, 2024
649c9a0
Merge remote-tracking branch 'origin/Enhancement/git_ssh_protocol' in…
diiinesh Oct 1, 2024
816bbaf
logging for git action build error
diiinesh Oct 1, 2024
ca7b2db
logging for git action build error
diiinesh Oct 1, 2024
42b5adc
Merge branch 'main' into Enhancement/git_ssh_protocol
hohwille Oct 2, 2024
8afd40a
revert logging code for searching error in git ci build, added worksp…
diiinesh Oct 8, 2024
1e39f35
Merge remote-tracking branch 'origin/Enhancement/git_ssh_protocol' in…
diiinesh Oct 8, 2024
d4ad4cf
Update cli/src/main/java/com/devonfw/tools/ide/variable/VariableDefin…
diiinesh Oct 23, 2024
5fc97d1
added javadoc
diiinesh Oct 23, 2024
f1039e9
Merge remote-tracking branch 'origin/Enhancement/git_ssh_protocol' in…
diiinesh Oct 23, 2024
35ef77e
added default value
diiinesh Oct 23, 2024
386089a
Merge branch 'main' into Enhancement/git_ssh_protocol
diiinesh Oct 23, 2024
b39addb
Merge remote-tracking branch 'diiinesh/Enhancement/git_ssh_protocol' …
alfeilex Oct 29, 2024
fafc51e
remove default value for PREFFERED_GIT_PROTOCOL
alfeilex Oct 29, 2024
2553c19
Update changelog
alfeilex Oct 29, 2024
86e85e5
Update CHANGELOG.adoc for re-build
alfeilex Oct 29, 2024
856a3c5
Merge branch 'main' into #312-enhance-git-syntax-urls
alfeilex Oct 30, 2024
c4ddf94
Add some changes for default behavior and add sytnax convert into git…
alfeilex Oct 30, 2024
a25aba8
Merge branch '#312-enhance-git-syntax-urls' of https://github.com/alf…
alfeilex Oct 30, 2024
bfc490b
Merge branch 'main' into #312-enhance-git-syntax-urls
alfeilex Nov 4, 2024
dec3410
Also format gitRepoUrl
alfeilex Nov 4, 2024
3db08c4
Remove parsedUrl and use .url() instead
alfeilex Nov 4, 2024
00c4e9b
Nothing changes if DEFAULT is set
alfeilex Nov 4, 2024
eabd338
refactor switch case syntax
alfeilex Nov 4, 2024
7d50d79
Merge branch 'main' into #312-enhance-git-syntax-urls
hohwille Nov 11, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The full list of changes for this release can be found in https://github.com/dev

Release with new features and bugfixes:

* https://github.com/devonfw/IDEasy/issues/312[#312]: Add ability to prefer git (ssh) protocol instead of https for cloning repo
* https://github.com/devonfw/IDEasy/issues/685[#685]: Upgrades and cleanup of dependencies and according license and doc
* https://github.com/devonfw/IDEasy/pull/693[#693]: Setup not working on Mac
* https://github.com/devonfw/IDEasy/issues/704[#704]: settings-security.xml not found
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.devonfw.tools.ide.context;

import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
Expand All @@ -11,6 +10,7 @@
import com.devonfw.tools.ide.process.ProcessErrorHandling;
import com.devonfw.tools.ide.process.ProcessMode;
import com.devonfw.tools.ide.process.ProcessResult;
import com.devonfw.tools.ide.variable.IdeVariables;

/**
* Implements the {@link GitContext}.
Expand Down Expand Up @@ -138,20 +138,21 @@ private void handleErrors(Path targetRepository, ProcessResult result) {
@Override
public void clone(GitUrl gitRepoUrl, Path targetRepository) {

URL parsedUrl = gitRepoUrl.parseUrl();
GitUrlSyntax gitUrlSyntax = IdeVariables.PREFERRED_GIT_PROTOCOL.get(getContext());
gitRepoUrl = gitUrlSyntax.format(gitRepoUrl);
this.processContext.directory(targetRepository);
ProcessResult result;
if (!this.context.isOffline()) {
this.context.getFileAccess().mkdirs(targetRepository);
this.context.requireOnline("git clone of " + parsedUrl);
this.context.requireOnline("git clone of " + gitRepoUrl.url());
this.processContext.addArg("clone");
if (this.context.isQuietMode()) {
this.processContext.addArg("-q");
}
this.processContext.addArgs("--recursive", gitRepoUrl.url(), "--config", "core.autocrlf=false", ".");
result = this.processContext.run(PROCESS_MODE);
if (!result.isSuccessful()) {
this.context.warning("Git failed to clone {} into {}.", parsedUrl, targetRepository);
this.context.warning("Git failed to clone {} into {}.", gitRepoUrl.url(), targetRepository);
}
String branch = gitRepoUrl.branch();
if (branch != null) {
Expand All @@ -162,7 +163,7 @@ public void clone(GitUrl gitRepoUrl, Path targetRepository) {
}
}
} else {
throw CliOfflineException.ofClone(parsedUrl, targetRepository);
throw CliOfflineException.ofClone(gitRepoUrl.parseUrl(), targetRepository);
}
}

Expand Down
10 changes: 10 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/context/GitUrl.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
*/
public record GitUrl(String url, String branch) {

/**
* Converts the Git URL based on the specified {@link GitUrlSyntax}.
*
* @param syntax the preferred {@link GitUrlSyntax} (SSH or HTTPS).
* @return the converted {@link GitUrl} or the original if no conversion is required.
*/
public GitUrl convert(GitUrlSyntax syntax) {
return syntax.format(this);
}

/**
* Parses a git URL and omits the branch name if not provided.
*
Expand Down
95 changes: 95 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/context/GitUrlSyntax.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.devonfw.tools.ide.context;

import java.util.Arrays;
import java.util.List;

/**
* Enum representing the syntax of Git URLs, either SSH or HTTPS. Provides methods to format and convert Git URLs based on the syntax.
*/
public enum GitUrlSyntax {

/**
* The DEFAULT Git URL syntax
*/
DEFAULT(""),
/**
* The SSH Git URL syntax (e.g., [email protected]:user/repo.git).
*/
SSH("git@"),

/**
* The HTTPS Git URL syntax (e.g., https://github.com/user/repo.git).
*/
HTTPS("https://");

private final String prefix;

private static final List<String> DOMAINS_WITH_NO_CONVERSION = Arrays.asList("github.com");

GitUrlSyntax(String prefix) {
this.prefix = prefix;
}

/**
* Formats the given Git URL according to the syntax represented by this enum constant.
* <p>
* Converts the URL between SSH and HTTPS formats. For example, an HTTPS URL can be converted to its corresponding SSH URL format, and vice versa.
* </p>
*
* @param gitUrl the original {@link GitUrl} to be formatted.
* @return the formatted {@link GitUrl} according to this syntax.
* @throws IllegalArgumentException if the protocol is not supported.
*/
public GitUrl format(GitUrl gitUrl) {
if (this == DEFAULT) {
return gitUrl;
}
String url = gitUrl.url();

// Prevent conversion for domains in the no-conversion list
if (isDomainWithNoConversion(url.toLowerCase())) {
return gitUrl;
}

switch (this) {
case SSH -> {
if (url.startsWith(HTTPS.prefix)) {
int index = url.indexOf("/", HTTPS.prefix.length());
if (index > 0) {
url = SSH.prefix + url.substring(HTTPS.prefix.length(), index) + ":" + url.substring(index + 1);
}
}
}
case HTTPS -> {
if (url.startsWith(SSH.prefix)) {
int index = url.indexOf(":");
if (index > 0) {
url = HTTPS.prefix + url.substring(SSH.prefix.length(), index) + "/" + url.substring(index + 1);
}
}
}
default -> throw new IllegalArgumentException("Unsupported protocol: " + this);
hohwille marked this conversation as resolved.
Show resolved Hide resolved
}

return new GitUrl(url, gitUrl.branch());
}

private boolean isDomainWithNoConversion(String url) {

for (String domain : DOMAINS_WITH_NO_CONVERSION) {
// Check if it's an HTTPS URL for the domain
if (url.startsWith("https://" + domain + "/")) {
return true;
}

// Check if it's an SSH URL for the domain
if (url.startsWith("git@" + domain + ":")) {
return true;
}
}

return false;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.Collection;
import java.util.List;

import com.devonfw.tools.ide.context.GitUrlSyntax;

/**
* Interface (mis)used to define all the available variables.
*/
Expand Down Expand Up @@ -73,6 +75,10 @@ public interface IdeVariables {
/** {@link VariableDefinition} for {@link com.devonfw.tools.ide.context.IdeContext#getProjectName() PROJECT_NAME}. */
VariableDefinitionString PROJECT_NAME = new VariableDefinitionString("PROJECT_NAME", null, c -> c.getProjectName());

/** Preferred Git protocol (HTTPS/SSH) as defined by {@link GitUrlSyntax}. */
VariableDefinitionEnum<GitUrlSyntax> PREFERRED_GIT_PROTOCOL = new VariableDefinitionEnum<>("PREFERRED_GIT_PROTOCOL", null, GitUrlSyntax.class,
c -> GitUrlSyntax.DEFAULT);

alfeilex marked this conversation as resolved.
Show resolved Hide resolved
/**
* {@link VariableDefinition} for support of legacy variable syntax when
* {@link com.devonfw.tools.ide.environment.EnvironmentVariables#resolve(String, Object, boolean) resolving variables} in configuration templates.
Expand All @@ -83,7 +89,7 @@ public interface IdeVariables {
/** A {@link Collection} with all pre-defined {@link VariableDefinition}s. */
Collection<VariableDefinition<?>> VARIABLES = List.of(PATH, HOME, WORKSPACE_PATH, IDE_HOME, IDE_ROOT, WORKSPACE, IDE_TOOLS, CREATE_START_SCRIPTS,
IDE_MIN_VERSION, MVN_VERSION, M2_REPO, DOCKER_EDITION, MVN_BUILD_OPTS, NPM_BUILD_OPTS, GRADLE_BUILD_OPTS, YARN_BUILD_OPTS, JASYPT_OPTS, MAVEN_ARGS,
PROJECT_NAME, IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED);
PROJECT_NAME, IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED, PREFERRED_GIT_PROTOCOL);

/**
* @param name the name of the requested {@link VariableDefinition}.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.devonfw.tools.ide.variable;

import java.util.function.Function;

import com.devonfw.tools.ide.context.IdeContext;

/**
* Implementation of {@link VariableDefinition} for a variable with the {@link #getValueType() value type} as an Enum.
*
* @param <E> the enum type.
*/
public class VariableDefinitionEnum<E extends Enum<E>> extends AbstractVariableDefinition<E> {

private final Class<E> enumType;

/**
* The constructor.
*
* @param name the {@link #getName() variable name}.
* @param enumType the class of the enum.
*/
public VariableDefinitionEnum(String name, Class<E> enumType) {
super(name);
this.enumType = enumType;
}

/**
* The constructor.
*
* @param name the {@link #getName() variable name}.
* @param legacyName the {@link #getLegacyName() legacy name}.
* @param enumType the class of the enum.
*/
public VariableDefinitionEnum(String name, String legacyName, Class<E> enumType) {
super(name, legacyName);
this.enumType = enumType;
}

/**
* The constructor.
*
* @param name the {@link #getName() variable name}.
* @param legacyName the {@link #getLegacyName() legacy name}.
* @param enumType the class of the enum.
* @param defaultValueFactory the factory {@link Function} for the {@link #getDefaultValue(IdeContext) default value}.
*/
public VariableDefinitionEnum(String name, String legacyName, Class<E> enumType, Function<IdeContext, E> defaultValueFactory) {
super(name, legacyName, defaultValueFactory);
this.enumType = enumType;
}

@Override
public Class<E> getValueType() {
return enumType;
}

/**
* Converts a string value to the corresponding enum constant. Converts the string to upper case before matching with the enum values.
*
* @param value the string representation of the enum.
* @param context the context for the current operation.
* @return the corresponding enum constant.
* @throws IllegalArgumentException if the string doesn't match any enum constant.
*/
@Override
public E fromString(String value, IdeContext context) {
return Enum.valueOf(enumType, value.toUpperCase(java.util.Locale.ROOT));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.devonfw.tools.ide.context;

import org.junit.jupiter.api.Test;

import com.devonfw.tools.ide.variable.IdeVariables;


/**
* Test class for verifying the behavior of Git URL conversions
*/
public class GitUrlSyntaxTest extends AbstractIdeContextTest {

/**
* Tests the reading of property PREFERRED_GIT_PROTOCOL from ide.properties is done successfully
*/
@Test
public void testPreferredGitProtocolIsReadAsSsh() {
// Read the PREFERRED_GIT_PROTOCOL from the config file
IdeTestContext context = newContext("git");
GitUrlSyntax preferredProtocol = IdeVariables.PREFERRED_GIT_PROTOCOL.get(context);

// Check if the configuration value is correctly set to SSH
assertThat(GitUrlSyntax.SSH).isEqualTo(preferredProtocol);
}

/**
* Tests the conversion of a Git URL from HTTPS to SSH protocol.
* <p>
* Given a Git URL in HTTPS format, this test ensures that it is correctly converted to the SSH format using the {@link GitUrl#convert(GitUrlSyntax)} method.
*/
@Test
public void testConvertGitUrlFromHttpsToSsh() {
String url = "https://testgitdomain.com/devonfw/IDEasy.git";
GitUrl gitUrl = new GitUrl(url, null);

// Use the convert method with GitUrlSyntax enum
GitUrl convertedGitUrl = gitUrl.convert(GitUrlSyntax.SSH);

String expectedSshUrl = "[email protected]:devonfw/IDEasy.git";
assertThat(convertedGitUrl.url()).isEqualTo(expectedSshUrl);
}

/**
* Tests the conversion of a Git URL from SSH to HTTPS protocol.
* <p>
* Given a Git URL in SSH format, this test ensures that it is correctly converted to the HTTPS format using the {@link GitUrl#convert(GitUrlSyntax)} method.
*/
@Test
public void testConvertGitUrlFromSshToHttps() {
String url = "[email protected]:devonfw/IDEasy.git";
GitUrl gitUrl = new GitUrl(url, null);

// Use the convert method with GitUrlSyntax enum
GitUrl convertedGitUrl = gitUrl.convert(GitUrlSyntax.HTTPS);

String expectedHttpsUrl = "https://testgitdomain.com/devonfw/IDEasy.git";
assertThat(convertedGitUrl.url()).isEqualTo(expectedHttpsUrl);
}

/**
* Tests that when a Git URL is in HTTPS format and points to the github.com domain, it remains in the original format and is not converted to SSH.
* <p>
* This test ensures that the Git URL for github.com stays in HTTPS format, even if SSH is specified as the preferred protocol.
*/
@Test
public void testConvertGitUrlGitHubDomain() {
String url = "https://github.com/devonfw/IDEasy.git";
GitUrl gitUrl = new GitUrl(url, null);

// Attempt to convert to SSH, but it should remain in HTTPS format for github.com
GitUrl convertedGitUrl = gitUrl.convert(GitUrlSyntax.SSH);

// The URL should remain unchanged in HTTPS format
assertThat(convertedGitUrl.url()).isEqualTo(url);
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PREFERRED_GIT_PROTOCOL=SSH
Empty file.
Loading