Skip to content

Commit a902b51

Browse files
committed
commit
1 parent f74ac9f commit a902b51

File tree

9 files changed

+131
-49
lines changed

9 files changed

+131
-49
lines changed

wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerURLParser.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public class BitbucketServerURLParser {
5353
private static final List<String> bitbucketUrlPatternTemplates =
5454
List.of(
5555
"^(?<scheme>%s)://(?<host>%s)/scm/~(?<user>[^/]+)/(?<repo>.*).git$",
56-
"^(?<scheme>%s)://(?<host>%s)/users/(?<user>[^/]+)/repos/(?<repo>[^/]+)/browse(\\?at=(?<branch>.*))?",
56+
"^(?<scheme>%s)://(?<host>%s)/users/(?<user>[^/]+)/repos/(?<repo>[^/]+)/browse((/(?<path>.+?))?(\\?at=(?<branch>.+))?)$",
5757
"^(?<scheme>%s)://(?<host>%s)/users/(?<user>[^/]+)/repos/(?<repo>[^/]+)/?",
5858
"^(?<scheme>%s)://(?<host>%s)/scm/(?<project>[^/~]+)/(?<repo>[^/]+).git",
59-
"^(?<scheme>%s)://(?<host>%s)/projects/(?<project>[^/]+)/repos/(?<repo>[^/]+)/browse(\\?at=(?<branch>.*))?",
59+
"^(?<scheme>%s)://(?<host>%s)/projects/(?<project>[^/]+)/repos/(?<repo>[^/]+)/browse((/(?<path>.+?))?(\\?at=(?<branch>.+))?)$",
6060
"^(?<scheme>%s)://git@(?<host>%s):(?<port>\\d*)/~(?<user>[^/]+)/(?<repo>.*).git$",
6161
"^(?<scheme>%s)://git@(?<host>%s):(?<port>\\d*)/(?<project>[^/]+)/(?<repo>.*).git$");
6262
private final List<Pattern> bitbucketUrlPatterns = new ArrayList<>();
@@ -224,11 +224,17 @@ private BitbucketServerUrl parse(Matcher matcher) {
224224
}
225225
String repoName = matcher.group("repo");
226226
String branch = null;
227+
String path = null;
227228
try {
228229
branch = matcher.group("branch");
229230
} catch (IllegalArgumentException e) {
230231
// keep branch with null, as the pattern doesn't have the branch group
231232
}
233+
try {
234+
path = matcher.group("path");
235+
} catch (IllegalArgumentException e) {
236+
// keep branch with null, as the pattern doesn't have the branch group
237+
}
232238

233239
return new BitbucketServerUrl()
234240
.withScheme(scheme)
@@ -238,6 +244,7 @@ private BitbucketServerUrl parse(Matcher matcher) {
238244
.withUser(user)
239245
.withRepository(repoName)
240246
.withBranch(branch)
247+
.withPath(path)
241248
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames());
242249
}
243250
}

wsmaster/che-core-api-factory-bitbucket-server/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketServerUrl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class BitbucketServerUrl extends DefaultFactoryUrl {
4343
/** Branch name */
4444
private String branch;
4545

46+
private String path;
47+
4648
/** Devfile filenames list */
4749
private final List<String> devfileFilenames = new ArrayList<>();
4850

@@ -141,6 +143,13 @@ protected BitbucketServerUrl withBranch(String branch) {
141143
return this;
142144
}
143145

146+
protected BitbucketServerUrl withPath(String path) {
147+
if (!isNullOrEmpty(path)) {
148+
this.path = path;
149+
}
150+
return this;
151+
}
152+
144153
/**
145154
* Gets user of this bitbucket server url
146155
*
@@ -196,7 +205,7 @@ public String rawFileLocation(String fileName) {
196205
.add("repos")
197206
.add(repository)
198207
.add("raw")
199-
.add(fileName);
208+
.add(isNullOrEmpty(path) ? fileName : path);
200209
String resultUrl = joiner.toString();
201210
if (branch != null) {
202211
resultUrl = resultUrl + "?at=" + branch;

wsmaster/che-core-api-factory-bitbucket/src/main/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketURLParser.java

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
*/
1212
package org.eclipse.che.api.factory.server.bitbucket;
1313

14+
import static java.lang.String.format;
15+
1416
import jakarta.validation.constraints.NotNull;
17+
import java.util.StringJoiner;
1518
import java.util.regex.Matcher;
1619
import java.util.regex.Pattern;
1720
import javax.inject.Inject;
@@ -22,35 +25,41 @@
2225
@Singleton
2326
public class BitbucketURLParser {
2427
private final DevfileFilenamesProvider devfileFilenamesProvider;
28+
private final Pattern bitbucketPattern;
2529

2630
@Inject
2731
public BitbucketURLParser(DevfileFilenamesProvider devfileFilenamesProvider) {
2832
this.devfileFilenamesProvider = devfileFilenamesProvider;
33+
StringJoiner stringJoiner = new StringJoiner("|");
34+
devfileFilenamesProvider
35+
.getConfiguredDevfileFilenames()
36+
.forEach(f -> stringJoiner.add(format("(%s)", f.replace(".", "\\."))).toString());
37+
/*
38+
Regexp to find repository details (repository name, workspace id, project name and branch)
39+
Examples of valid URLs are in the test class.
40+
*/
41+
String bitbucketPatternTemplate =
42+
format(
43+
"^https?://(?<username>[^/@]+)?@?bitbucket\\.org/(?<workspaceId>[^/]+)/(?<repoName>[^/]+)/?(\\.git)?(/(src|branch)/(?<path>.+?)/?(%s)?)?$",
44+
stringJoiner);
45+
this.bitbucketPattern = Pattern.compile(bitbucketPatternTemplate);
2946
}
3047

31-
/**
32-
* Regexp to find repository details (repository name, workspace id, project name and branch)
33-
* Examples of valid URLs are in the test class.
34-
*/
35-
protected static final Pattern BITBUCKET_PATTERN =
36-
Pattern.compile(
37-
"^https?://(?<username>[^/@]+)?@?bitbucket\\.org/(?<workspaceId>[^/]+)/(?<repoName>[^/]+)/?(\\.git)?(/(src|branch)/(?<branchName>[^/]+)/?)?$");
38-
3948
protected static final Pattern BITBUCKET_SSH_PATTERN =
4049
Pattern.compile("^[email protected]:(?<workspaceId>.*)/(?<repoName>.*)$");
4150

4251
public boolean isValid(@NotNull String url) {
43-
return BITBUCKET_PATTERN.matcher(url).matches() || BITBUCKET_SSH_PATTERN.matcher(url).matches();
52+
return bitbucketPattern.matcher(url).matches() || BITBUCKET_SSH_PATTERN.matcher(url).matches();
4453
}
4554

4655
public BitbucketUrl parse(String url) {
4756
// Apply bitbucket url to the regexp
48-
boolean isHTTPSUrl = BITBUCKET_PATTERN.matcher(url).matches();
57+
boolean isHTTPSUrl = bitbucketPattern.matcher(url).matches();
4958
Matcher matcher =
50-
isHTTPSUrl ? BITBUCKET_PATTERN.matcher(url) : BITBUCKET_SSH_PATTERN.matcher(url);
59+
isHTTPSUrl ? bitbucketPattern.matcher(url) : BITBUCKET_SSH_PATTERN.matcher(url);
5160
if (!matcher.matches()) {
5261
throw new IllegalArgumentException(
53-
String.format("The given bitbucket url %s is not a valid URL bitbucket url. ", url));
62+
format("The given bitbucket url %s is not a valid URL bitbucket url. ", url));
5463
}
5564

5665
String workspaceId = matcher.group("workspaceId");
@@ -59,17 +68,17 @@ public BitbucketUrl parse(String url) {
5968
repoName = repoName.substring(0, repoName.length() - 4);
6069
}
6170
String username = null;
62-
String branchName = null;
71+
String path = null;
6372
if (isHTTPSUrl) {
6473
username = matcher.group("username");
65-
branchName = matcher.group("branchName");
74+
path = matcher.group("path");
6675
}
6776

6877
return new BitbucketUrl()
6978
.withUsername(username)
7079
.withRepository(repoName)
7180
.setIsHTTPSUrl(isHTTPSUrl)
72-
.withBranch(branchName)
81+
.withBranch(path)
7382
.withWorkspaceId(workspaceId)
7483
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames())
7584
.withUrl(url);

wsmaster/che-core-api-factory-bitbucket/src/test/java/org/eclipse/che/api/factory/server/bitbucket/BitbucketURLParserTest.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
*/
1212
package org.eclipse.che.api.factory.server.bitbucket;
1313

14+
import static java.util.Arrays.asList;
1415
import static org.mockito.ArgumentMatchers.any;
1516
import static org.mockito.Mockito.lenient;
17+
import static org.mockito.Mockito.when;
1618
import static org.testng.Assert.assertEquals;
1719
import static org.testng.Assert.assertTrue;
1820

1921
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
2022
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
21-
import org.mockito.InjectMocks;
2223
import org.mockito.Mock;
2324
import org.mockito.testng.MockitoTestNGListener;
2425
import org.testng.annotations.BeforeMethod;
@@ -34,11 +35,14 @@ public class BitbucketURLParserTest {
3435
@Mock private DevfileFilenamesProvider devfileFilenamesProvider;
3536

3637
/** Instance of component that will be tested. */
37-
@InjectMocks private BitbucketURLParser bitbucketURLParser;
38+
private BitbucketURLParser bitbucketURLParser;
3839

3940
@BeforeMethod
4041
public void init() {
42+
when(devfileFilenamesProvider.getConfiguredDevfileFilenames())
43+
.thenReturn(asList("devfile.yaml", ".devfile.yaml"));
4144
lenient().when(urlFetcher.fetchSafely(any(String.class))).thenReturn("");
45+
bitbucketURLParser = new BitbucketURLParser(devfileFilenamesProvider);
4246
}
4347

4448
/** Check URLs are valid with regexp */
@@ -122,7 +126,19 @@ public Object[][] expectedParsing() {
122126
{"[email protected]:eclipse/che-with-hyphen.git", "eclipse", "che-with-hyphen", null},
123127
{"[email protected]:eclipse/repositorygit", "eclipse", "repositorygit", null},
124128
{"https://bitbucket.org/eclipse/che/src/4.2.x", "eclipse", "che", "4.2.x"},
125-
{"https://bitbucket.org/eclipse/che/src/master/", "eclipse", "che", "master"}
129+
{"https://bitbucket.org/eclipse/che/src/master/", "eclipse", "che", "master"},
130+
{
131+
"https://bitbucket.org/eclipse/che/src/branch/path/to/devfile.yaml",
132+
"eclipse",
133+
"che",
134+
"branch/path/to"
135+
},
136+
{
137+
"https://bitbucket.org/eclipse/che/src/branch/path/to/.devfile.yaml",
138+
"eclipse",
139+
"che",
140+
"branch/path/to"
141+
}
126142
};
127143
}
128144

wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubURLParser.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.net.URI;
2424
import java.net.URISyntaxException;
2525
import java.util.Optional;
26+
import java.util.StringJoiner;
2627
import java.util.regex.Matcher;
2728
import java.util.regex.Pattern;
2829
import org.eclipse.che.api.core.ApiException;
@@ -52,8 +53,7 @@ public abstract class AbstractGithubURLParser {
5253
*/
5354
private final Pattern githubPattern;
5455

55-
private final String githubPatternTemplate =
56-
"^%s/(?<repoUser>[^/]+)/(?<repoName>[^/]++)((/)|(?:/tree/(?<branchName>.++))|(/pull/(?<pullRequestId>\\d++)))?$";
56+
private final String githubPatternTemplate;
5757

5858
private final Pattern githubSSHPattern;
5959

@@ -86,6 +86,14 @@ public abstract class AbstractGithubURLParser {
8686

8787
endpoint = isNullOrEmpty(oauthEndpoint) ? GITHUB_SAAS_ENDPOINT : trimEnd(oauthEndpoint, '/');
8888

89+
StringJoiner stringJoiner = new StringJoiner("|");
90+
devfileFilenamesProvider
91+
.getConfiguredDevfileFilenames()
92+
.forEach(f -> stringJoiner.add(format("(%s)", f.replace(".", "\\."))).toString());
93+
githubPatternTemplate =
94+
format(
95+
"%s/(?<repoUser>[^/]+)/(?<repoName>[^/]++)((/)|(?:/((tree)|(blob))/(?<path>.+?)/?(%s)?)|(/pull/(?<pullRequestId>\\d++)))?$",
96+
"%s", stringJoiner);
8997
this.githubPattern = compile(format(githubPatternTemplate, endpoint));
9098
this.githubSSHPattern =
9199
compile(format(githubSSHPatternTemplate, URI.create(endpoint).getHost()));
@@ -204,10 +212,10 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx
204212
repoName = repoName.substring(0, repoName.length() - 4);
205213
}
206214

207-
String branchName = null;
215+
String path = null;
208216
String pullRequestId = null;
209217
if (isHTTPSUrl) {
210-
branchName = matcher.group("branchName");
218+
path = matcher.group("path");
211219
pullRequestId = matcher.group("pullRequestId");
212220
}
213221

@@ -226,18 +234,14 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx
226234
GithubHead pullRequestHead = pullRequest.getHead();
227235
repoUser = pullRequestHead.getUser().getLogin();
228236
repoName = pullRequestHead.getRepo().getName();
229-
branchName = pullRequestHead.getRef();
237+
path = pullRequestHead.getRef();
230238
}
231239
}
232240

233241
String latestCommit = null;
234242
GithubCommit commit =
235243
getLatestCommit(
236-
serverUrl,
237-
repoUser,
238-
repoName,
239-
firstNonNull(branchName, "HEAD"),
240-
authenticationRequired);
244+
serverUrl, repoUser, repoName, firstNonNull(path, "HEAD"), authenticationRequired);
241245
if (commit != null) {
242246
latestCommit = commit.getSha();
243247
}
@@ -248,7 +252,7 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx
248252
.setIsHTTPSUrl(isHTTPSUrl)
249253
.withServerUrl(serverUrl)
250254
.withDisableSubdomainIsolation(disableSubdomainIsolation)
251-
.withBranch(branchName)
255+
.withBranch(path)
252256
.withLatestCommit(latestCommit)
253257
.withDevfileFilenames(devfileFilenamesProvider.getConfiguredDevfileFilenames())
254258
.withUrl(url);

wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubURLParserTest.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
1818
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
1919
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
20+
import static java.util.Arrays.asList;
2021
import static org.mockito.ArgumentMatchers.any;
2122
import static org.mockito.ArgumentMatchers.anyString;
2223
import static org.mockito.ArgumentMatchers.eq;
@@ -38,6 +39,7 @@
3839
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
3940
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
4041
import org.eclipse.che.commons.subject.Subject;
42+
import org.mockito.Mock;
4143
import org.mockito.testng.MockitoTestNGListener;
4244
import org.testng.annotations.BeforeMethod;
4345
import org.testng.annotations.DataProvider;
@@ -55,6 +57,7 @@ public class GithubURLParserTest {
5557
private GithubApiClient githubApiClient;
5658

5759
private PersonalAccessTokenManager personalAccessTokenManager;
60+
@Mock private DevfileFilenamesProvider devfileFilenamesProvider;
5861

5962
/** Instance of component that will be tested. */
6063
private GithubURLParser githubUrlParser;
@@ -72,14 +75,12 @@ protected void start() throws ApiException {
7275
wireMock = new WireMock("localhost", wireMockServer.port());
7376
this.personalAccessTokenManager = mock(PersonalAccessTokenManager.class);
7477
this.githubApiClient = mock(GithubApiClient.class);
78+
when(devfileFilenamesProvider.getConfiguredDevfileFilenames())
79+
.thenReturn(asList("devfile.yaml", ".devfile.yaml"));
7580

7681
githubUrlParser =
7782
new GithubURLParser(
78-
personalAccessTokenManager,
79-
mock(DevfileFilenamesProvider.class),
80-
githubApiClient,
81-
null,
82-
false);
83+
personalAccessTokenManager, devfileFilenamesProvider, githubApiClient, null, false);
8384
}
8485

8586
/** Check invalid url (not a GitHub one) */
@@ -96,13 +97,13 @@ public void checkRegexp(String url) {
9697

9798
/** Compare parsing */
9899
@Test(dataProvider = "parsing")
99-
public void checkParsing(String url, String username, String repository, String branch)
100+
public void checkParsing(String url, String username, String repository, String path)
100101
throws ApiException {
101102
GithubUrl githubUrl = githubUrlParser.parse(url);
102103

103104
assertEquals(githubUrl.getUsername(), username);
104105
assertEquals(githubUrl.getRepository(), repository);
105-
assertEquals(githubUrl.getBranch(), branch);
106+
assertEquals(githubUrl.getBranch(), path);
106107
}
107108

108109
/** Compare parsing */
@@ -160,12 +161,31 @@ public Object[][] expectedParsing() {
160161
{"https://github.com/eclipse/repositorygit", "eclipse", "repositorygit", null},
161162
{"https://github.com/eclipse/che/tree/4.2.x", "eclipse", "che", "4.2.x"},
162163
{"https://github.com/eclipse/che/tree/master", "eclipse", "che", "master"},
164+
{"https://github.com/eclipse/che/tree/master/", "eclipse", "che", "master"},
163165
{
164166
"https://github.com/eclipse/che/tree/branch/with/slash",
165167
"eclipse",
166168
"che",
167169
"branch/with/slash"
168170
},
171+
{
172+
"https://github.com/eclipse/che/blob/branch/path/to/",
173+
"eclipse",
174+
"che",
175+
"branch/path/to"
176+
},
177+
{
178+
"https://github.com/eclipse/che/blob/branch/path/to/devfile.yaml",
179+
"eclipse",
180+
"che",
181+
"branch/path/to"
182+
},
183+
{
184+
"https://github.com/eclipse/che/blob/branch/path/to/.devfile.yaml",
185+
"eclipse",
186+
"che",
187+
"branch/path/to"
188+
},
169189
{"[email protected]:eclipse/che", "eclipse", "che", null},
170190
{"[email protected]:eclipse/che123", "eclipse", "che123", null},
171191
{"[email protected]:eclipse/che.git", "eclipse", "che", null},

0 commit comments

Comments
 (0)