diff --git a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProvider.java b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProvider.java
index 166b0151fa..1137407b94 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProvider.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProvider.java
@@ -29,12 +29,7 @@ class GitlabAuthorizingFileContentProvider extends AuthorizingFileContentProvide
@Override
protected boolean isPublicRepository(GitlabUrl remoteFactoryUrl) {
try {
- urlFetcher.fetch(
- remoteFactoryUrl.getHostName()
- + '/'
- + remoteFactoryUrl.getUsername()
- + '/'
- + remoteFactoryUrl.getProject());
+ urlFetcher.fetch(remoteFactoryUrl.getHostName() + '/' + remoteFactoryUrl.getSubGroups());
return true;
} catch (IOException e) {
return false;
diff --git a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrl.java b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrl.java
index 22edaa7451..1e581bc255 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrl.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrl.java
@@ -25,8 +25,8 @@ import org.eclipse.che.api.factory.server.urlfactory.DefaultFactoryUrl;
/**
* Representation of a gitlab URL, allowing to get details from it.
*
- *
like https://gitlab.com//
- * https://gitlab.com///-/tree/
+ * like https://gitlab.com/path/to/repository or
+ * https://gitlab.com/path/to/repository/-/tree/
*
* @author Max Shaposhnyk
*/
@@ -37,14 +37,14 @@ public class GitlabUrl extends DefaultFactoryUrl {
/** Hostname of the gitlab URL */
private String hostName;
- /** Username part of the gitlab URL */
- private String username;
-
/** Project part of the gitlab URL */
private String project;
- /** Repository part of the gitlab URL. */
- private String repository;
+ /**
+ * Incorporates subgroups in the project path of the gitlab URL. See details at:
+ * https://docs.gitlab.com/ee/user/group/subgroups/
+ */
+ private String subGroups;
/** Branch name */
private String branch;
@@ -80,20 +80,6 @@ public class GitlabUrl extends DefaultFactoryUrl {
return this;
}
- /**
- * Gets username of this gitlab url
- *
- * @return the username part
- */
- public String getUsername() {
- return this.username;
- }
-
- public GitlabUrl withUsername(String userName) {
- this.username = userName;
- return this;
- }
-
/**
* Gets project of this bitbucket url
*
@@ -103,22 +89,16 @@ public class GitlabUrl extends DefaultFactoryUrl {
return this.project;
}
- public GitlabUrl withProject(String project) {
- this.project = project;
- return this;
+ public String getSubGroups() {
+ return subGroups;
}
- /**
- * Gets repository of this gitlab url
- *
- * @return the repository part
- */
- public String getRepository() {
- return this.repository;
- }
+ protected GitlabUrl withSubGroups(String subGroups) {
+ this.subGroups = subGroups;
- protected GitlabUrl withRepository(String repository) {
- this.repository = repository;
+ String[] subGroupsItems = subGroups.split("/");
+ this.project =
+ subGroupsItems[subGroupsItems.length - 1]; // project (repository) name is the last item
return this;
}
@@ -204,7 +184,7 @@ public class GitlabUrl extends DefaultFactoryUrl {
.add(hostName)
.add("api/v4/projects")
// use URL-encoded path to the project as a selector instead of id
- .add(geProjectIdentifier())
+ .add(encode(subGroups, Charsets.UTF_8))
.add("repository")
.add("files")
.add(encode(fileName, Charsets.UTF_8))
@@ -217,22 +197,12 @@ public class GitlabUrl extends DefaultFactoryUrl {
return resultUrl;
}
- private String geProjectIdentifier() {
- return repository != null
- ? encode(username + "/" + project + "/" + repository, Charsets.UTF_8)
- : encode(username + "/" + project, Charsets.UTF_8);
- }
-
/**
* Provides location to the repository part of the full gitlab URL.
*
* @return location of the repository.
*/
protected String repositoryLocation() {
- if (repository == null) {
- return hostName + "/" + this.username + "/" + this.project + ".git";
- } else {
- return hostName + "/" + this.username + "/" + this.project + "/" + repository + ".git";
- }
+ return hostName + "/" + subGroups + ".git";
}
}
diff --git a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParser.java b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParser.java
index c35eef3f82..f25cbd7f8e 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParser.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/main/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParser.java
@@ -14,6 +14,7 @@ package org.eclipse.che.api.factory.server.gitlab;
import static java.lang.String.format;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static java.util.regex.Pattern.compile;
+import static org.eclipse.che.commons.lang.StringUtils.trimEnd;
import com.google.common.base.Splitter;
import jakarta.validation.constraints.NotNull;
@@ -33,7 +34,6 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
-import org.eclipse.che.commons.lang.StringUtils;
/**
* Parser of String Gitlab URLs and provide {@link GitlabUrl} objects.
@@ -46,10 +46,9 @@ public class GitlabUrlParser {
private final PersonalAccessTokenManager personalAccessTokenManager;
private static final List gitlabUrlPatternTemplates =
List.of(
- "^(?%s)/(?[^/]++)/(?[^./]++).git",
- "^(?%s)/(?[^/]++)/(?[^/]++)/(?[^.]++).git",
- "^(?%s)/(?[^/]++)/(?[^/]++)(/)?(?[^/]++)?(/)?",
- "^(?%s)/(?[^/]++)/(?[^/]++)(/)?(?[^/]++)?/-/tree/(?[^/]++)(/)?(?[^/]++)?");
+ "^(?%s)/(?([^/]++/?)+)/-/tree/(?[^/]++)(/)?(?[^/]++)?",
+ "^(?%s)/(?.*)"); // a wider one, should be the last in the
+ // list
private final List gitlabUrlPatterns = new ArrayList<>();
private static final String OAUTH_PROVIDER_NAME = "gitlab";
@@ -62,7 +61,7 @@ public class GitlabUrlParser {
this.personalAccessTokenManager = personalAccessTokenManager;
if (gitlabEndpoints != null) {
for (String gitlabEndpoint : Splitter.on(",").split(gitlabEndpoints)) {
- String trimmedEndpoint = StringUtils.trimEnd(gitlabEndpoint, '/');
+ String trimmedEndpoint = trimEnd(gitlabEndpoint, '/');
for (String gitlabUrlPatternTemplate : gitlabUrlPatternTemplates) {
gitlabUrlPatterns.add(compile(format(gitlabUrlPatternTemplate, trimmedEndpoint)));
}
@@ -163,16 +162,13 @@ public class GitlabUrlParser {
private GitlabUrl parse(Matcher matcher) {
String host = matcher.group("host");
- String userName = matcher.group("user");
- String project = matcher.group("project");
- String repository = null;
+ String subGroups = trimEnd(matcher.group("subgroups"), '/');
+ if (subGroups.endsWith(".git")) {
+ subGroups = subGroups.substring(0, subGroups.length() - 4);
+ }
+
String branch = null;
String subfolder = null;
- try {
- repository = matcher.group("repository");
- } catch (IllegalArgumentException e) {
- // ok no such group
- }
try {
branch = matcher.group("branch");
} catch (IllegalArgumentException e) {
@@ -186,9 +182,7 @@ public class GitlabUrlParser {
return new GitlabUrl()
.withHostName(host)
- .withUsername(userName)
- .withProject(project)
- .withRepository(repository)
+ .withSubGroups(subGroups)
.withBranch(branch)
.withSubfolder(subfolder)
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames());
diff --git a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProviderTest.java b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProviderTest.java
index 92ea30aa7a..165621e62e 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProviderTest.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabAuthorizingFileContentProviderTest.java
@@ -33,10 +33,7 @@ public class GitlabAuthorizingFileContentProviderTest {
public void shouldExpandRelativePaths() throws Exception {
URLFetcher urlFetcher = Mockito.mock(URLFetcher.class);
GitlabUrl gitlabUrl =
- new GitlabUrl()
- .withHostName("https://gitlab.net")
- .withUsername("eclipse")
- .withProject("che");
+ new GitlabUrl().withHostName("https://gitlab.net").withSubGroups("eclipse/che");
FileContentProvider fileContentProvider =
new GitlabAuthorizingFileContentProvider(gitlabUrl, urlFetcher, personalAccessTokenManager);
var personalAccessToken = new PersonalAccessToken("foo", "che", "my-token");
@@ -52,8 +49,7 @@ public class GitlabAuthorizingFileContentProviderTest {
@Test
public void shouldPreserveAbsolutePaths() throws Exception {
URLFetcher urlFetcher = Mockito.mock(URLFetcher.class);
- GitlabUrl gitlabUrl =
- new GitlabUrl().withHostName("gitlab.net").withUsername("eclipse").withProject("che");
+ GitlabUrl gitlabUrl = new GitlabUrl().withHostName("gitlab.net").withSubGroups("eclipse/che");
FileContentProvider fileContentProvider =
new GitlabAuthorizingFileContentProvider(gitlabUrl, urlFetcher, personalAccessTokenManager);
String url =
diff --git a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolverTest.java b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolverTest.java
index 59a6a2b9f0..6fa25c1497 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolverTest.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabFactoryParametersResolverTest.java
@@ -118,7 +118,7 @@ public class GitlabFactoryParametersResolverTest {
// when
FactoryDto factory = (FactoryDto) gitlabFactoryParametersResolver.createFactory(params);
// then
- verify(urlFactoryBuilder).buildDefaultDevfile(eq("proj"));
+ verify(urlFactoryBuilder).buildDefaultDevfile(eq("repo"));
assertEquals(factory, computedFactory);
SourceDto source = factory.getDevfile().getProjects().get(0).getSource();
assertEquals(source.getLocation(), gitlabUrl);
diff --git a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParserTest.java b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParserTest.java
index 94931742b8..c9e13812d2 100644
--- a/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParserTest.java
+++ b/wsmaster/che-core-api-factory-gitlab/src/test/java/org/eclipse/che/api/factory/server/gitlab/GitlabUrlParserTest.java
@@ -72,12 +72,11 @@ public class GitlabUrlParserTest {
/** Compare parsing */
@Test(dataProvider = "parsing")
public void checkParsing(
- String url, String user, String project, String repository, String branch, String subfolder) {
+ String url, String project, String subGroups, String branch, String subfolder) {
GitlabUrl gitlabUrl = gitlabUrlParser.parse(url);
- assertEquals(gitlabUrl.getUsername(), user);
assertEquals(gitlabUrl.getProject(), project);
- assertEquals(gitlabUrl.getRepository(), repository);
+ assertEquals(gitlabUrl.getSubGroups(), subGroups);
assertEquals(gitlabUrl.getBranch(), branch);
assertEquals(gitlabUrl.getSubfolder(), subfolder);
}
@@ -124,16 +123,31 @@ public class GitlabUrlParserTest {
@DataProvider(name = "parsing")
public Object[][] expectedParsing() {
return new Object[][] {
- {"https://gitlab1.com/user/project1.git", "user", "project1", null, null, null},
- {"https://gitlab1.com/user/project/test1.git", "user", "project", "test1", null, null},
- {"https://gitlab1.com/user/project/", "user", "project", null, null, null},
- {"https://gitlab1.com/user/project/repo/", "user", "project", "repo", null, null},
- {"https://gitlab1.com/user/project/-/tree/master/", "user", "project", null, "master", null},
+ {"https://gitlab1.com/user/project1.git", "project1", "user/project1", null, null},
+ {"https://gitlab1.com/user/project/test1.git", "test1", "user/project/test1", null, null},
+ {
+ "https://gitlab1.com/user/project/group1/group2/test1.git",
+ "test1",
+ "user/project/group1/group2/test1",
+ null,
+ null
+ },
+ {"https://gitlab1.com/user/project/", "project", "user/project", null, null},
+ {"https://gitlab1.com/user/project/repo/", "repo", "user/project/repo", null, null},
+ {
+ "https://gitlab1.com/user/project/-/tree/master/", "project", "user/project", "master", null
+ },
{
"https://gitlab1.com/user/project/repo/-/tree/foo/subfolder",
- "user",
- "project",
"repo",
+ "user/project/repo",
+ "foo",
+ "subfolder"
+ },
+ {
+ "https://gitlab1.com/user/project/group1/group2/repo/-/tree/foo/subfolder",
+ "repo",
+ "user/project/group1/group2/repo",
"foo",
"subfolder"
}