Omit extracting subfolder from a workspace URL (#523)
sparce-checkoutis no longer available from devfile 2.1, so omit the subfolder mechanism in order to support branch names with a / sign.pull/528/head
parent
fbea05f0cc
commit
ab83bee400
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2021 Red Hat, Inc.
|
* Copyright (c) 2012-2023 Red Hat, Inc.
|
||||||
* This program and the accompanying materials are made
|
* This program and the accompanying materials are made
|
||||||
* available under the terms of the Eclipse Public License 2.0
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
|
@ -13,7 +13,6 @@ package org.eclipse.che.api.factory.server.github;
|
||||||
|
|
||||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
@ -40,9 +39,6 @@ public class GithubSourceStorageBuilder {
|
||||||
Map<String, String> parameters = new HashMap<>(2);
|
Map<String, String> parameters = new HashMap<>(2);
|
||||||
parameters.put("branch", githubUrl.getBranch());
|
parameters.put("branch", githubUrl.getBranch());
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(githubUrl.getSubfolder())) {
|
|
||||||
parameters.put("keepDir", githubUrl.getSubfolder());
|
|
||||||
}
|
|
||||||
return newDto(SourceStorageDto.class)
|
return newDto(SourceStorageDto.class)
|
||||||
.withLocation(githubUrl.repositoryLocation())
|
.withLocation(githubUrl.repositoryLocation())
|
||||||
.withType("github")
|
.withType("github")
|
||||||
|
|
@ -59,7 +55,6 @@ public class GithubSourceStorageBuilder {
|
||||||
return newDto(SourceDto.class)
|
return newDto(SourceDto.class)
|
||||||
.withLocation(githubUrl.repositoryLocation())
|
.withLocation(githubUrl.repositoryLocation())
|
||||||
.withType("github")
|
.withType("github")
|
||||||
.withBranch(githubUrl.getBranch())
|
.withBranch(githubUrl.getBranch());
|
||||||
.withSparseCheckoutDir(githubUrl.getSubfolder());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,20 +99,20 @@ public class GithubURLParser {
|
||||||
this.githubPattern =
|
this.githubPattern =
|
||||||
compile(
|
compile(
|
||||||
format(
|
format(
|
||||||
"^%s/(?<repoUser>[^/]++)/(?<repoName>[^/]++)((/)|(?:/tree/(?<branchName>[^/]++)(?:/(?<subFolder>.*))?)|(/pull/(?<pullRequestId>[^/]++)))?$",
|
"^%s/(?<repoUser>[^/]+)/(?<repoName>[^/]++)((/)|(?:/tree/(?<branchName>.++))|(/pull/(?<pullRequestId>\\d++)))?$",
|
||||||
endpoint));
|
endpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid(@NotNull String url) {
|
public boolean isValid(@NotNull String url) {
|
||||||
return githubPattern.matcher(url).matches();
|
return githubPattern.matcher(trimEnd(url, '/')).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GithubUrl parseWithoutAuthentication(String url) throws ApiException {
|
public GithubUrl parseWithoutAuthentication(String url) throws ApiException {
|
||||||
return parse(url, false);
|
return parse(trimEnd(url, '/'), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GithubUrl parse(String url) throws ApiException {
|
public GithubUrl parse(String url) throws ApiException {
|
||||||
return parse(url, true);
|
return parse(trimEnd(url, '/'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GithubUrl parse(String url, boolean authenticationRequired) throws ApiException {
|
private GithubUrl parse(String url, boolean authenticationRequired) throws ApiException {
|
||||||
|
|
@ -173,7 +173,6 @@ public class GithubURLParser {
|
||||||
.withDisableSubdomainIsolation(disableSubdomainIsolation)
|
.withDisableSubdomainIsolation(disableSubdomainIsolation)
|
||||||
.withBranch(branchName)
|
.withBranch(branchName)
|
||||||
.withLatestCommit(latestCommit)
|
.withLatestCommit(latestCommit)
|
||||||
.withSubfolder(matcher.group("subFolder"))
|
|
||||||
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames())
|
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames())
|
||||||
.withUrl(url);
|
.withUrl(url);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,6 @@ public class GithubUrl extends DefaultFactoryUrl {
|
||||||
/** SHA of the latest commit in the current branch */
|
/** SHA of the latest commit in the current branch */
|
||||||
private String latestCommit;
|
private String latestCommit;
|
||||||
|
|
||||||
/** Subfolder if any */
|
|
||||||
private String subfolder;
|
|
||||||
|
|
||||||
private String serverUrl;
|
private String serverUrl;
|
||||||
|
|
||||||
private boolean disableSubdomainIsolation;
|
private boolean disableSubdomainIsolation;
|
||||||
|
|
@ -143,26 +140,6 @@ public class GithubUrl extends DefaultFactoryUrl {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets subfolder of this github url
|
|
||||||
*
|
|
||||||
* @return the subfolder part
|
|
||||||
*/
|
|
||||||
public String getSubfolder() {
|
|
||||||
return this.subfolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subfolder represented by the URL.
|
|
||||||
*
|
|
||||||
* @param subfolder path inside the repository
|
|
||||||
* @return current github instance
|
|
||||||
*/
|
|
||||||
protected GithubUrl withSubfolder(String subfolder) {
|
|
||||||
this.subfolder = subfolder;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GithubUrl withServerUrl(String serverUrl) {
|
public GithubUrl withServerUrl(String serverUrl) {
|
||||||
this.serverUrl = serverUrl;
|
this.serverUrl = serverUrl;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -76,15 +76,13 @@ public class GithubURLParserTest {
|
||||||
|
|
||||||
/** Compare parsing */
|
/** Compare parsing */
|
||||||
@Test(dataProvider = "parsing")
|
@Test(dataProvider = "parsing")
|
||||||
public void checkParsing(
|
public void checkParsing(String url, String username, String repository, String branch)
|
||||||
String url, String username, String repository, String branch, String subfolder)
|
|
||||||
throws ApiException {
|
throws ApiException {
|
||||||
GithubUrl githubUrl = githubUrlParser.parse(url);
|
GithubUrl githubUrl = githubUrlParser.parse(url);
|
||||||
|
|
||||||
assertEquals(githubUrl.getUsername(), username);
|
assertEquals(githubUrl.getUsername(), username);
|
||||||
assertEquals(githubUrl.getRepository(), repository);
|
assertEquals(githubUrl.getRepository(), repository);
|
||||||
assertEquals(githubUrl.getBranch(), branch);
|
assertEquals(githubUrl.getBranch(), branch);
|
||||||
assertEquals(githubUrl.getSubfolder(), subfolder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compare parsing */
|
/** Compare parsing */
|
||||||
|
|
@ -117,31 +115,24 @@ public class GithubURLParserTest {
|
||||||
@DataProvider(name = "parsing")
|
@DataProvider(name = "parsing")
|
||||||
public Object[][] expectedParsing() {
|
public Object[][] expectedParsing() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
{"https://github.com/eclipse/che", "eclipse", "che", null, null},
|
{"https://github.com/eclipse/che", "eclipse", "che", null},
|
||||||
{"https://github.com/eclipse/che123", "eclipse", "che123", null, null},
|
{"https://github.com/eclipse/che123", "eclipse", "che123", null},
|
||||||
{"https://github.com/eclipse/che.git", "eclipse", "che", null, null},
|
{"https://github.com/eclipse/che.git", "eclipse", "che", null},
|
||||||
{"https://github.com/eclipse/che.with.dot.git", "eclipse", "che.with.dot", null, null},
|
{"https://github.com/eclipse/che.with.dot.git", "eclipse", "che.with.dot", null},
|
||||||
{"https://github.com/eclipse/-.git", "eclipse", "-", null, null},
|
{"https://github.com/eclipse/-.git", "eclipse", "-", null},
|
||||||
{"https://github.com/eclipse/-j.git", "eclipse", "-j", null, null},
|
{"https://github.com/eclipse/-j.git", "eclipse", "-j", null},
|
||||||
{"https://github.com/eclipse/-", "eclipse", "-", null, null},
|
{"https://github.com/eclipse/-", "eclipse", "-", null},
|
||||||
{"https://github.com/eclipse/che-with-hyphen", "eclipse", "che-with-hyphen", null, null},
|
{"https://github.com/eclipse/che-with-hyphen", "eclipse", "che-with-hyphen", null},
|
||||||
{"https://github.com/eclipse/che-with-hyphen.git", "eclipse", "che-with-hyphen", null, null},
|
{"https://github.com/eclipse/che-with-hyphen.git", "eclipse", "che-with-hyphen", null},
|
||||||
{"https://github.com/eclipse/che/", "eclipse", "che", null, null},
|
{"https://github.com/eclipse/che/", "eclipse", "che", null},
|
||||||
{"https://github.com/eclipse/repositorygit", "eclipse", "repositorygit", null, null},
|
{"https://github.com/eclipse/repositorygit", "eclipse", "repositorygit", null},
|
||||||
{"https://github.com/eclipse/che/tree/4.2.x", "eclipse", "che", "4.2.x", null},
|
{"https://github.com/eclipse/che/tree/4.2.x", "eclipse", "che", "4.2.x"},
|
||||||
|
{"https://github.com/eclipse/che/tree/master", "eclipse", "che", "master"},
|
||||||
{
|
{
|
||||||
"https://github.com/eclipse/che/tree/master/dashboard/",
|
"https://github.com/eclipse/che/tree/branch/with/slash",
|
||||||
"eclipse",
|
"eclipse",
|
||||||
"che",
|
"che",
|
||||||
"master",
|
"branch/with/slash"
|
||||||
"dashboard/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://github.com/eclipse/che/tree/master/plugins/plugin-git/che-plugin-git-ext-git",
|
|
||||||
"eclipse",
|
|
||||||
"che",
|
|
||||||
"master",
|
|
||||||
"plugins/plugin-git/che-plugin-git-ext-git"
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,7 @@ public class GitlabFactoryParametersResolver extends RawDevfileUrlFactoryParamet
|
||||||
newDto(SourceDto.class)
|
newDto(SourceDto.class)
|
||||||
.withLocation(gitlabUrl.repositoryLocation())
|
.withLocation(gitlabUrl.repositoryLocation())
|
||||||
.withType("git")
|
.withType("git")
|
||||||
.withBranch(gitlabUrl.getBranch())
|
.withBranch(gitlabUrl.getBranch()))
|
||||||
.withSparseCheckoutDir(gitlabUrl.getSubfolder()))
|
|
||||||
.withName(gitlabUrl.getProject()),
|
.withName(gitlabUrl.getProject()),
|
||||||
project -> {
|
project -> {
|
||||||
final String location = project.getSource().getLocation();
|
final String location = project.getSource().getLocation();
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,6 @@ public class GitlabUrl extends DefaultFactoryUrl {
|
||||||
/** Branch name */
|
/** Branch name */
|
||||||
private String branch;
|
private String branch;
|
||||||
|
|
||||||
/** Subfolder if any */
|
|
||||||
private String subfolder;
|
|
||||||
|
|
||||||
/** Devfile filenames list */
|
/** Devfile filenames list */
|
||||||
private final List<String> devfileFilenames = new ArrayList<>();
|
private final List<String> devfileFilenames = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -129,26 +126,6 @@ public class GitlabUrl extends DefaultFactoryUrl {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets subfolder of this gitlab url
|
|
||||||
*
|
|
||||||
* @return the subfolder part
|
|
||||||
*/
|
|
||||||
public String getSubfolder() {
|
|
||||||
return this.subfolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subfolder represented by the URL.
|
|
||||||
*
|
|
||||||
* @param subfolder path inside the repository
|
|
||||||
* @return current gitlab URL instance
|
|
||||||
*/
|
|
||||||
protected GitlabUrl withSubfolder(String subfolder) {
|
|
||||||
this.subfolder = subfolder;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides list of configured devfile filenames with locations
|
* Provides list of configured devfile filenames with locations
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class GitlabUrlParser {
|
||||||
private final PersonalAccessTokenManager personalAccessTokenManager;
|
private final PersonalAccessTokenManager personalAccessTokenManager;
|
||||||
private static final List<String> gitlabUrlPatternTemplates =
|
private static final List<String> gitlabUrlPatternTemplates =
|
||||||
List.of(
|
List.of(
|
||||||
"^(?<host>%s)/(?<subgroups>([^/]++/?)+)/-/tree/(?<branch>[^/]++)(/)?(?<subfolder>[^/]++)?",
|
"^(?<host>%s)/(?<subgroups>([^/]++/?)+)/-/tree/(?<branch>.++)(/)?",
|
||||||
"^(?<host>%s)/(?<subgroups>.*)"); // a wider one, should be the last in the
|
"^(?<host>%s)/(?<subgroups>.*)"); // a wider one, should be the last in the
|
||||||
// list
|
// list
|
||||||
private final List<Pattern> gitlabUrlPatterns = new ArrayList<>();
|
private final List<Pattern> gitlabUrlPatterns = new ArrayList<>();
|
||||||
|
|
@ -93,7 +93,8 @@ public class GitlabUrlParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid(@NotNull String url) {
|
public boolean isValid(@NotNull String url) {
|
||||||
return gitlabUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches())
|
return gitlabUrlPatterns.stream()
|
||||||
|
.anyMatch(pattern -> pattern.matcher(trimEnd(url, '/')).matches())
|
||||||
// If the Gitlab URL is not configured, try to find it in a manually added user namespace
|
// If the Gitlab URL is not configured, try to find it in a manually added user namespace
|
||||||
// token.
|
// token.
|
||||||
|| isUserTokenPresent(url)
|
|| isUserTokenPresent(url)
|
||||||
|
|
@ -144,15 +145,15 @@ public class GitlabUrlParser {
|
||||||
* {@link GitlabUrl} objects.
|
* {@link GitlabUrl} objects.
|
||||||
*/
|
*/
|
||||||
public GitlabUrl parse(String url) {
|
public GitlabUrl parse(String url) {
|
||||||
|
String trimmedUrl = trimEnd(url, '/');
|
||||||
Optional<Matcher> matcherOptional =
|
Optional<Matcher> matcherOptional =
|
||||||
gitlabUrlPatterns.stream()
|
gitlabUrlPatterns.stream()
|
||||||
.map(pattern -> pattern.matcher(url))
|
.map(pattern -> pattern.matcher(trimmedUrl))
|
||||||
.filter(Matcher::matches)
|
.filter(Matcher::matches)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.or(() -> getPatternMatcherByUrl(url));
|
.or(() -> getPatternMatcherByUrl(trimmedUrl));
|
||||||
if (matcherOptional.isPresent()) {
|
if (matcherOptional.isPresent()) {
|
||||||
return parse(matcherOptional.get()).withUrl(url);
|
return parse(matcherOptional.get()).withUrl(trimmedUrl);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"The gitlab integration is not configured properly and cannot be used at this moment."
|
"The gitlab integration is not configured properly and cannot be used at this moment."
|
||||||
|
|
@ -168,23 +169,16 @@ public class GitlabUrlParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
String branch = null;
|
String branch = null;
|
||||||
String subfolder = null;
|
|
||||||
try {
|
try {
|
||||||
branch = matcher.group("branch");
|
branch = matcher.group("branch");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// ok no such group
|
// ok no such group
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
subfolder = matcher.group("subfolder");
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
// ok no such group
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GitlabUrl()
|
return new GitlabUrl()
|
||||||
.withHostName(host)
|
.withHostName(host)
|
||||||
.withSubGroups(subGroups)
|
.withSubGroups(subGroups)
|
||||||
.withBranch(branch)
|
.withBranch(branch)
|
||||||
.withSubfolder(subfolder)
|
|
||||||
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames());
|
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,12 @@ public class GitlabUrlParserTest {
|
||||||
|
|
||||||
/** Compare parsing */
|
/** Compare parsing */
|
||||||
@Test(dataProvider = "parsing")
|
@Test(dataProvider = "parsing")
|
||||||
public void checkParsing(
|
public void checkParsing(String url, String project, String subGroups, String branch) {
|
||||||
String url, String project, String subGroups, String branch, String subfolder) {
|
|
||||||
GitlabUrl gitlabUrl = gitlabUrlParser.parse(url);
|
GitlabUrl gitlabUrl = gitlabUrlParser.parse(url);
|
||||||
|
|
||||||
assertEquals(gitlabUrl.getProject(), project);
|
assertEquals(gitlabUrl.getProject(), project);
|
||||||
assertEquals(gitlabUrl.getSubGroups(), subGroups);
|
assertEquals(gitlabUrl.getSubGroups(), subGroups);
|
||||||
assertEquals(gitlabUrl.getBranch(), branch);
|
assertEquals(gitlabUrl.getBranch(), branch);
|
||||||
assertEquals(gitlabUrl.getSubfolder(), subfolder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -123,33 +121,29 @@ public class GitlabUrlParserTest {
|
||||||
@DataProvider(name = "parsing")
|
@DataProvider(name = "parsing")
|
||||||
public Object[][] expectedParsing() {
|
public Object[][] expectedParsing() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
{"https://gitlab1.com/user/project1.git", "project1", "user/project1", null, null},
|
{"https://gitlab1.com/user/project1.git", "project1", "user/project1", null},
|
||||||
{"https://gitlab1.com/user/project/test1.git", "test1", "user/project/test1", null, null},
|
{"https://gitlab1.com/user/project/test1.git", "test1", "user/project/test1", null},
|
||||||
{
|
{
|
||||||
"https://gitlab1.com/user/project/group1/group2/test1.git",
|
"https://gitlab1.com/user/project/group1/group2/test1.git",
|
||||||
"test1",
|
"test1",
|
||||||
"user/project/group1/group2/test1",
|
"user/project/group1/group2/test1",
|
||||||
null,
|
|
||||||
null
|
null
|
||||||
},
|
},
|
||||||
{"https://gitlab1.com/user/project/", "project", "user/project", null, null},
|
{"https://gitlab1.com/user/project/", "project", "user/project", null},
|
||||||
{"https://gitlab1.com/user/project/repo/", "repo", "user/project/repo", null, null},
|
{"https://gitlab1.com/user/project/repo/", "repo", "user/project/repo", null},
|
||||||
|
{"https://gitlab1.com/user/project/-/tree/master/", "project", "user/project", "master"},
|
||||||
|
{"https://gitlab1.com/user/project/repo/-/tree/foo", "repo", "user/project/repo", "foo"},
|
||||||
{
|
{
|
||||||
"https://gitlab1.com/user/project/-/tree/master/", "project", "user/project", "master", null
|
"https://gitlab1.com/user/project/repo/-/tree/branch/with/slash",
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://gitlab1.com/user/project/repo/-/tree/foo/subfolder",
|
|
||||||
"repo",
|
"repo",
|
||||||
"user/project/repo",
|
"user/project/repo",
|
||||||
"foo",
|
"branch/with/slash"
|
||||||
"subfolder"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"https://gitlab1.com/user/project/group1/group2/repo/-/tree/foo/subfolder",
|
"https://gitlab1.com/user/project/group1/group2/repo/-/tree/foo/",
|
||||||
"repo",
|
"repo",
|
||||||
"user/project/group1/group2/repo",
|
"user/project/group1/group2/repo",
|
||||||
"foo",
|
"foo"
|
||||||
"subfolder"
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,10 +85,6 @@ public class GitlabUrlTest {
|
||||||
"https://gitlab.net/eclipse/fooproj/che/-/tree/foobranch/",
|
"https://gitlab.net/eclipse/fooproj/che/-/tree/foobranch/",
|
||||||
"https://gitlab.net/api/v4/projects/eclipse%%2Ffooproj%%2Fche/repository/files/%s/raw?ref=foobranch"
|
"https://gitlab.net/api/v4/projects/eclipse%%2Ffooproj%%2Fche/repository/files/%s/raw?ref=foobranch"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"https://gitlab.net/eclipse/fooproj/che/-/tree/foobranch/subfolder",
|
|
||||||
"https://gitlab.net/api/v4/projects/eclipse%%2Ffooproj%%2Fche/repository/files/%s/raw?ref=foobranch"
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue