mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-01 11:05:56 +01:00
merge
This commit is contained in:
1
.mvn/wrapper/maven-wrapper.properties
vendored
1
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1 +1,2 @@
|
||||
# Keep this version number in sync with Jenkinsfile
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
|
||||
|
||||
13
Jenkinsfile
vendored
13
Jenkinsfile
vendored
@@ -11,16 +11,14 @@ node() { // No specific label
|
||||
|
||||
properties([
|
||||
// Keep only the last 10 build to preserve space
|
||||
buildDiscarder(logRotator(numToKeepStr: '10')),
|
||||
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||
])
|
||||
|
||||
timeout(activity: true, time: 20, unit: 'MINUTES') {
|
||||
|
||||
catchError {
|
||||
|
||||
Maven mvn = setupMavenBuild()
|
||||
// Maven build specified it must be 1.8.0-101 or newer
|
||||
def javaHome = tool 'JDK-1.8.0-101+'
|
||||
|
||||
withEnv(["JAVA_HOME=${javaHome}", "PATH=${env.JAVA_HOME}/bin:${env.PATH}"]) {
|
||||
|
||||
stage('Checkout') {
|
||||
checkout scm
|
||||
@@ -47,7 +45,6 @@ node() { // No specific label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Archive Unit and integration test results, if any
|
||||
junit allowEmptyResults: true, testResults: '**/target/failsafe-reports/TEST-*.xml,**/target/surefire-reports/TEST-*.xml,**/target/jest-reports/TEST-*.xml'
|
||||
@@ -56,12 +53,14 @@ node() { // No specific label
|
||||
warnings consoleParsers: [[parserName: 'Maven']], canRunOnFailed: true
|
||||
|
||||
mailIfStatusChanged(commitAuthorEmail)
|
||||
}
|
||||
}
|
||||
|
||||
String mainBranch
|
||||
|
||||
Maven setupMavenBuild() {
|
||||
Maven mvn = new MavenWrapper(this)
|
||||
// Keep this version number in sync with .mvn/maven-wrapper.properties
|
||||
Maven mvn = new MavenInDocker(this, "3.5.2-jdk-8")
|
||||
|
||||
if (mainBranch.equals(env.BRANCH_NAME)) {
|
||||
// Release starts javadoc, which takes very long, so do only for certain branches
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -430,7 +430,9 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||
<version>1.17</version>
|
||||
<!-- Note: 1.17 seems to have problems with JDK8. When updating, use > 1.17, if available!
|
||||
https://github.com/mojohaus/animal-sniffer/issues/53 -->
|
||||
<version>1.16</version>
|
||||
<configuration>
|
||||
<signature>
|
||||
<groupId>org.codehaus.mojo.signature</groupId>
|
||||
|
||||
@@ -33,9 +33,8 @@ package sonia.scm.plugin;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* The WebResourceLoader is able to load web resources. The resources are loaded
|
||||
@@ -53,9 +52,11 @@ public interface WebResourceLoader
|
||||
* Returns a {@link URL} for the given path. The method will return null if no
|
||||
* resources could be found for the given path.
|
||||
*
|
||||
* Note: The path is a web path and uses "/" as path separator
|
||||
*
|
||||
* @param path resource path
|
||||
*
|
||||
* @return url object for the given path or null
|
||||
*/
|
||||
public URL getResource(String path);
|
||||
URL getResource(String path);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package sonia.scm.util;
|
||||
|
||||
public class CRLFInjectionException extends IllegalArgumentException{
|
||||
|
||||
public CRLFInjectionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -344,8 +344,7 @@ public final class HttpUtil
|
||||
"parameter \"{}\" contains a character which could be an indicator for a crlf injection",
|
||||
parameter);
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"parameter contains an illegal character");
|
||||
throw new CRLFInjectionException("parameter contains an illegal character");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ public class VndMediaType {
|
||||
private static final String SUBTYPE_PREFIX = "vnd.scmm-";
|
||||
public static final String PREFIX = TYPE + "/" + SUBTYPE_PREFIX;
|
||||
public static final String SUFFIX = "+json;v=" + VERSION;
|
||||
public static final String PLAIN_TEXT_PREFIX = "text/" + SUBTYPE_PREFIX;
|
||||
public static final String PLAIN_TEXT_SUFFIX = "+plain;v=" + VERSION;
|
||||
|
||||
public static final String USER = PREFIX + "user" + SUFFIX;
|
||||
public static final String GROUP = PREFIX + "group" + SUFFIX;
|
||||
@@ -23,6 +25,7 @@ public class VndMediaType {
|
||||
public static final String TAG = PREFIX + "tag" + SUFFIX;
|
||||
public static final String TAG_COLLECTION = PREFIX + "tagCollection" + SUFFIX;
|
||||
public static final String BRANCH = PREFIX + "branch" + SUFFIX;
|
||||
public static final String DIFF = PLAIN_TEXT_PREFIX + "diff" + PLAIN_TEXT_SUFFIX;
|
||||
public static final String USER_COLLECTION = PREFIX + "userCollection" + SUFFIX;
|
||||
public static final String GROUP_COLLECTION = PREFIX + "groupCollection" + SUFFIX;
|
||||
public static final String REPOSITORY_COLLECTION = PREFIX + "repositoryCollection" + SUFFIX;
|
||||
|
||||
@@ -37,6 +37,7 @@ public class RepositoryAccessITCase {
|
||||
|
||||
private final String repositoryType;
|
||||
private File folder;
|
||||
private RepositoryRequests.AppliedRepositoryGetRequest repositoryGetRequest;
|
||||
|
||||
public RepositoryAccessITCase(String repositoryType) {
|
||||
this.repositoryType = repositoryType;
|
||||
@@ -48,9 +49,15 @@ public class RepositoryAccessITCase {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initClient() {
|
||||
public void init() {
|
||||
TestData.createDefault();
|
||||
folder = tempFolder.getRoot();
|
||||
repositoryGetRequest = RepositoryRequests.start()
|
||||
.given()
|
||||
.url(TestData.getDefaultRepositoryUrl(repositoryType))
|
||||
.usernameAndPassword(ADMIN_USERNAME, ADMIN_PASSWORD)
|
||||
.get()
|
||||
.assertStatusCode(HttpStatus.SC_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -246,5 +253,64 @@ public class RepositoryAccessITCase {
|
||||
|
||||
assertThat(changesets).size().isBetween(2, 3); // svn has an implicit root revision '0' that is extra to the two commits
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFindDiffs() throws IOException {
|
||||
RepositoryClient repositoryClient = RepositoryUtil.createRepositoryClient(repositoryType, folder);
|
||||
|
||||
RepositoryUtil.createAndCommitFile(repositoryClient, "scmadmin", "a.txt", "a");
|
||||
RepositoryUtil.createAndCommitFile(repositoryClient, "scmadmin", "b.txt", "b");
|
||||
|
||||
String changesetsUrl = given()
|
||||
.when()
|
||||
.get(TestData.getDefaultRepositoryUrl(repositoryType))
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.extract()
|
||||
.path("_links.changesets.href");
|
||||
|
||||
String diffUrl = given()
|
||||
.when()
|
||||
.get(changesetsUrl)
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.extract()
|
||||
.path("_embedded.changesets[0]._links.diff.href");
|
||||
|
||||
given()
|
||||
.when()
|
||||
.get(diffUrl)
|
||||
.then()
|
||||
.statusCode(HttpStatus.SC_OK)
|
||||
.extract()
|
||||
.body()
|
||||
.asString()
|
||||
.contains("diff");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldFindFileHistory() throws IOException {
|
||||
RepositoryClient repositoryClient = RepositoryUtil.createRepositoryClient(repositoryType, folder);
|
||||
Changeset changeset = RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, "folder/subfolder/a.txt", "a");
|
||||
repositoryGetRequest
|
||||
.usingRepositoryResponse()
|
||||
.requestSources()
|
||||
.usingSourcesResponse()
|
||||
.requestSelf("folder")
|
||||
.usingSourcesResponse()
|
||||
.requestSelf("subfolder")
|
||||
.usingSourcesResponse()
|
||||
.requestFileHistory("a.txt")
|
||||
.assertStatusCode(HttpStatus.SC_OK)
|
||||
.usingChangesetsResponse()
|
||||
.assertChangesets(changesets -> {
|
||||
assertThat(changesets).hasSize(1);
|
||||
assertThat(changesets.get(0)).containsEntry("id", changeset.getId());
|
||||
assertThat(changesets.get(0)).containsEntry("description", changeset.getDescription());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
249
scm-it/src/test/java/sonia/scm/it/RepositoryRequests.java
Normal file
249
scm-it/src/test/java/sonia/scm/it/RepositoryRequests.java
Normal file
@@ -0,0 +1,249 @@
|
||||
package sonia.scm.it;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
* Encapsulate rest requests of a repository in builder pattern
|
||||
* <p>
|
||||
* A Get Request can be applied with the methods request*()
|
||||
* These methods return a AppliedGet*Request object
|
||||
* This object can be used to apply general assertions over the rest Assured response
|
||||
* In the AppliedGet*Request classes there is a using*Response() method
|
||||
* that return the *Response class containing specific operations related to the specific response
|
||||
* the *Response class contains also the request*() method to apply the next GET request from a link in the response.
|
||||
*/
|
||||
public class RepositoryRequests {
|
||||
|
||||
private String url;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
static RepositoryRequests start() {
|
||||
return new RepositoryRequests();
|
||||
}
|
||||
|
||||
Given given() {
|
||||
return new Given();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply a GET Request to the extracted url from the given link
|
||||
*
|
||||
* @param linkPropertyName the property name of link
|
||||
* @param response the response containing the link
|
||||
* @return the response of the GET request using the given link
|
||||
*/
|
||||
private Response getResponseFromLink(Response response, String linkPropertyName) {
|
||||
return getResponse(response
|
||||
.then()
|
||||
.extract()
|
||||
.path(linkPropertyName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply a GET Request to the given <code>url</code> and return the response.
|
||||
*
|
||||
* @param url the url of the GET request
|
||||
* @return the response of the GET request using the given <code>url</code>
|
||||
*/
|
||||
private Response getResponse(String url) {
|
||||
return RestAssured.given()
|
||||
.auth().preemptive().basic(username, password)
|
||||
.when()
|
||||
.get(url);
|
||||
}
|
||||
|
||||
private void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
private void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
private void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
private String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
private String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
private String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
class Given {
|
||||
|
||||
GivenUrl url(String url) {
|
||||
setUrl(url);
|
||||
return new GivenUrl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GivenWithUrlAndAuth {
|
||||
AppliedRepositoryGetRequest get() {
|
||||
return new AppliedRepositoryGetRequest(
|
||||
getResponse(url)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppliedGetRequest<SELF extends AppliedGetRequest> {
|
||||
private Response response;
|
||||
|
||||
public AppliedGetRequest(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* apply custom assertions to the actual response
|
||||
*
|
||||
* @param consumer consume the response in order to assert the content. the header, the payload etc..
|
||||
* @return the self object
|
||||
*/
|
||||
SELF assertResponse(Consumer<Response> consumer) {
|
||||
consumer.accept(response);
|
||||
return (SELF) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* special assertion of the status code
|
||||
*
|
||||
* @param expectedStatusCode the expected status code
|
||||
* @return the self object
|
||||
*/
|
||||
SELF assertStatusCode(int expectedStatusCode) {
|
||||
this.response.then().assertThat().statusCode(expectedStatusCode);
|
||||
return (SELF) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AppliedRepositoryGetRequest extends AppliedGetRequest<AppliedRepositoryGetRequest> {
|
||||
|
||||
AppliedRepositoryGetRequest(Response response) {
|
||||
super(response);
|
||||
}
|
||||
|
||||
RepositoryResponse usingRepositoryResponse() {
|
||||
return new RepositoryResponse(super.response);
|
||||
}
|
||||
}
|
||||
|
||||
class RepositoryResponse {
|
||||
|
||||
private Response repositoryResponse;
|
||||
|
||||
public RepositoryResponse(Response repositoryResponse) {
|
||||
this.repositoryResponse = repositoryResponse;
|
||||
}
|
||||
|
||||
AppliedGetSourcesRequest requestSources() {
|
||||
return new AppliedGetSourcesRequest(getResponseFromLink(repositoryResponse, "_links.sources.href"));
|
||||
}
|
||||
|
||||
AppliedGetChangesetsRequest requestChangesets(String fileName) {
|
||||
return new AppliedGetChangesetsRequest(getResponseFromLink(repositoryResponse, "_links.changesets.href"));
|
||||
}
|
||||
}
|
||||
|
||||
class AppliedGetChangesetsRequest extends AppliedGetRequest<AppliedGetChangesetsRequest> {
|
||||
|
||||
AppliedGetChangesetsRequest(Response response) {
|
||||
super(response);
|
||||
}
|
||||
|
||||
ChangesetsResponse usingChangesetsResponse() {
|
||||
return new ChangesetsResponse(super.response);
|
||||
}
|
||||
}
|
||||
|
||||
class ChangesetsResponse {
|
||||
private Response changesetsResponse;
|
||||
|
||||
public ChangesetsResponse(Response changesetsResponse) {
|
||||
this.changesetsResponse = changesetsResponse;
|
||||
}
|
||||
|
||||
ChangesetsResponse assertChangesets(Consumer<List<Map>> changesetsConsumer) {
|
||||
List<Map> changesets = changesetsResponse.then().extract().path("_embedded.changesets");
|
||||
changesetsConsumer.accept(changesets);
|
||||
return this;
|
||||
}
|
||||
|
||||
AppliedGetDiffRequest requestDiff(String revision) {
|
||||
return new AppliedGetDiffRequest(getResponseFromLink(changesetsResponse, "_embedded.changesets.find{it.id=='" + revision + "'}._links.diff.href"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AppliedGetSourcesRequest extends AppliedGetRequest<AppliedGetSourcesRequest> {
|
||||
|
||||
public AppliedGetSourcesRequest(Response sourcesResponse) {
|
||||
super(sourcesResponse);
|
||||
}
|
||||
|
||||
SourcesResponse usingSourcesResponse() {
|
||||
return new SourcesResponse(super.response);
|
||||
}
|
||||
}
|
||||
|
||||
class SourcesResponse {
|
||||
|
||||
private Response sourcesResponse;
|
||||
|
||||
SourcesResponse(Response sourcesResponse) {
|
||||
this.sourcesResponse = sourcesResponse;
|
||||
}
|
||||
|
||||
SourcesResponse assertRevision(Consumer<String> assertRevision) {
|
||||
String revision = sourcesResponse.then().extract().path("revision");
|
||||
assertRevision.accept(revision);
|
||||
return this;
|
||||
}
|
||||
|
||||
SourcesResponse assertFiles(Consumer<List> assertFiles) {
|
||||
List files = sourcesResponse.then().extract().path("files");
|
||||
assertFiles.accept(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
AppliedGetChangesetsRequest requestFileHistory(String fileName) {
|
||||
return new AppliedGetChangesetsRequest(getResponseFromLink(sourcesResponse, "_embedded.files.find{it.name=='" + fileName + "'}._links.history.href"));
|
||||
}
|
||||
|
||||
AppliedGetSourcesRequest requestSelf(String fileName) {
|
||||
return new AppliedGetSourcesRequest(getResponseFromLink(sourcesResponse, "_embedded.files.find{it.name=='" + fileName + "'}._links.self.href"));
|
||||
}
|
||||
}
|
||||
|
||||
class AppliedGetDiffRequest extends AppliedGetRequest<AppliedGetDiffRequest> {
|
||||
|
||||
AppliedGetDiffRequest(Response response) {
|
||||
super(response);
|
||||
}
|
||||
}
|
||||
|
||||
class GivenUrl {
|
||||
|
||||
GivenWithUrlAndAuth usernameAndPassword(String username, String password) {
|
||||
setUsername(username);
|
||||
setPassword(password);
|
||||
return new GivenWithUrlAndAuth();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public class RepositoryUtil {
|
||||
|
||||
static Changeset createAndCommitFile(RepositoryClient repositoryClient, String username, String fileName, String content) throws IOException {
|
||||
File file = new File(repositoryClient.getWorkingCopy(), fileName);
|
||||
Files.createParentDirs(file);
|
||||
Files.write(content, file, Charsets.UTF_8);
|
||||
addWithParentDirectories(repositoryClient, file);
|
||||
return commit(repositoryClient, username, "added " + fileName);
|
||||
@@ -53,7 +54,6 @@ public class RepositoryUtil {
|
||||
String thisName = file.getName();
|
||||
String path;
|
||||
if (!repositoryClient.getWorkingCopy().equals(parent)) {
|
||||
addWithParentDirectories(repositoryClient, parent);
|
||||
path = addWithParentDirectories(repositoryClient, parent) + File.separator + thisName;
|
||||
} else {
|
||||
path = thisName;
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
"@scm-manager/ui-extensions": "^0.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13"
|
||||
"@scm-manager/ui-bundler": "^0.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,9 +707,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -737,9 +737,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -1867,7 +1868,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3285,7 +3286,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -4733,6 +4747,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -4955,6 +4979,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -6402,7 +6430,7 @@ source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -6857,6 +6885,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -7033,6 +7068,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
"@scm-manager/ui-extensions": "^0.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13"
|
||||
"@scm-manager/ui-bundler": "^0.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { Image } from "@scm-manager/ui-components";
|
||||
import {Image} from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
};
|
||||
@@ -8,7 +8,7 @@ type Props = {
|
||||
class HgAvatar extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
return <Image src="/scm/images/hg-logo.png" alt="Mercurial Logo" />;
|
||||
return <Image src="/images/hg-logo.png" alt="Mercurial Logo" />;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -641,9 +641,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -671,9 +671,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -1801,7 +1802,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3217,7 +3218,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -4636,6 +4650,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -4868,6 +4892,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -6283,7 +6311,7 @@ source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -6739,6 +6767,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -6915,6 +6950,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
"@scm-manager/ui-extensions": "^0.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13"
|
||||
"@scm-manager/ui-bundler": "^0.0.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { Image } from "@scm-manager/ui-components";
|
||||
import {Image} from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
};
|
||||
@@ -8,7 +8,7 @@ type Props = {
|
||||
class SvnAvatar extends React.Component<Props> {
|
||||
|
||||
render() {
|
||||
return <Image src="/scm/images/svn-logo.gif" alt="Subversion Logo" />;
|
||||
return <Image src="/images/svn-logo.gif" alt="Subversion Logo" />;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -641,9 +641,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -671,9 +671,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -1801,7 +1802,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3217,7 +3218,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -4636,6 +4650,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -4868,6 +4892,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -6283,7 +6311,7 @@ source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -6739,6 +6767,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -6915,6 +6950,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"eslint-fix": "eslint src --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13",
|
||||
"@scm-manager/ui-bundler": "^0.0.15",
|
||||
"create-index": "^2.3.0",
|
||||
"enzyme": "^3.5.0",
|
||||
"enzyme-adapter-react-16": "^1.3.1",
|
||||
|
||||
@@ -728,9 +728,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -758,9 +758,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -1983,7 +1984,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3605,7 +3606,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -5264,6 +5278,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -5506,6 +5530,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -7143,7 +7171,7 @@ source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -7627,6 +7655,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -7839,6 +7874,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"check": "flow check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13"
|
||||
"@scm-manager/ui-bundler": "^0.0.15"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
||||
@@ -707,9 +707,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -737,9 +737,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -1856,7 +1857,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3252,7 +3253,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -4693,6 +4707,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -4915,6 +4939,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -6327,7 +6355,7 @@ source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -6778,6 +6806,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -6954,6 +6989,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
"redux-thunk": "^2.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"webfonts": "copyfiles -f node_modules/@fortawesome/fontawesome-free/webfonts/* target/styles/webfonts",
|
||||
"build-css": "node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/styles",
|
||||
"watch-css": "npm run build-css && node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/styles --watch --recursive",
|
||||
"start-js": "ui-bundler serve --vendor vendor.bundle.js",
|
||||
"webfonts": "copyfiles -f node_modules/@fortawesome/fontawesome-free/webfonts/* target/scm-ui/styles/webfonts",
|
||||
"build-css": "node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/scm-ui/styles",
|
||||
"watch-css": "npm run build-css && node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/scm-ui/styles --watch --recursive",
|
||||
"start-js": "ui-bundler serve --target target/scm-ui --vendor vendor.bundle.js",
|
||||
"start": "npm-run-all -p webfonts watch-css start-js",
|
||||
"build-js": "ui-bundler bundle target/scm-ui.bundle.js",
|
||||
"build-vendor": "ui-bundler vendor target/vendor.bundle.js",
|
||||
"build-js": "ui-bundler bundle --mode=production target/scm-ui/scm-ui.bundle.js",
|
||||
"build-vendor": "ui-bundler vendor --mode=production target/scm-ui/vendor.bundle.js",
|
||||
"build": "npm-run-all -s webfonts build-css build-vendor build-js",
|
||||
"test": "ui-bundler test",
|
||||
"test-ci": "ui-bundler test --ci",
|
||||
@@ -42,7 +42,7 @@
|
||||
"pre-commit": "jest && flow && eslint src"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@scm-manager/ui-bundler": "^0.0.13",
|
||||
"@scm-manager/ui-bundler": "^0.0.15",
|
||||
"copyfiles": "^2.0.0",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>sonia.scm.clients</groupId>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-ui</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<packaging>war</packaging>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<name>scm-ui</name>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<finalName>scm-ui</finalName>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
@@ -93,6 +94,20 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>public</directory>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -8,20 +8,11 @@
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="/scm/manifest.json">
|
||||
<link rel="shortcut icon" href="/scm/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
<link rel="manifest" href="{{ contextPath }}/manifest.json">
|
||||
<link rel="shortcut icon" href="{{ contextPath }}/favicon.ico">
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<base href="/scm">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/scm/styles/scm.css">
|
||||
<base href="{{ contextPath }}">
|
||||
<link rel="stylesheet" type="text/css" href="{{ contextPath }}/styles/scm.css">
|
||||
|
||||
<title>SCM-Manager</title>
|
||||
</head>
|
||||
@@ -41,9 +32,9 @@
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script>
|
||||
window.ctxPath = "/scm";
|
||||
window.ctxPath = "{{ contextPath }}";
|
||||
</script>
|
||||
<script src="/scm/vendor.bundle.js"></script>
|
||||
<script src="/scm/scm-ui.bundle.js"></script>
|
||||
<script src="{{ contextPath }}/vendor.bundle.js"></script>
|
||||
<script src="{{ contextPath }}/scm-ui.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -732,9 +732,9 @@
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85"
|
||||
|
||||
"@scm-manager/ui-bundler@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4"
|
||||
"@scm-manager/ui-bundler@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917"
|
||||
dependencies:
|
||||
"@babel/core" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.0.0"
|
||||
@@ -762,9 +762,10 @@
|
||||
flow-bin "^0.79.1"
|
||||
gulp "^3.9.1"
|
||||
gulp-sourcemaps "^2.6.4"
|
||||
gulp-util "^3.0.8"
|
||||
gulp-uglify "^3.0.1"
|
||||
jest "^23.5.0"
|
||||
jest-junit "^5.1.0"
|
||||
mustache "^2.3.2"
|
||||
node-mkdirs "^0.0.1"
|
||||
pom-parser "^1.1.1"
|
||||
prettier "^1.14.2"
|
||||
@@ -2042,7 +2043,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined-
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0:
|
||||
commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1:
|
||||
version "2.17.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
|
||||
|
||||
@@ -3743,7 +3744,20 @@ gulp-sourcemaps@^2.6.4:
|
||||
strip-bom-string "1.X"
|
||||
through2 "2.X"
|
||||
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.8:
|
||||
gulp-uglify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97"
|
||||
dependencies:
|
||||
gulplog "^1.0.0"
|
||||
has-gulplog "^0.1.0"
|
||||
lodash "^4.13.1"
|
||||
make-error-cause "^1.1.1"
|
||||
safe-buffer "^5.1.2"
|
||||
through2 "^2.0.0"
|
||||
uglify-js "^3.0.5"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
gulp-util@^3.0.0:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -5474,6 +5488,16 @@ lru-queue@0.1:
|
||||
dependencies:
|
||||
es5-ext "~0.10.2"
|
||||
|
||||
make-error-cause@^1.1.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d"
|
||||
dependencies:
|
||||
make-error "^1.2.0"
|
||||
|
||||
make-error@^1.2.0:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
@@ -5743,6 +5767,10 @@ multipipe@^0.1.2:
|
||||
dependencies:
|
||||
duplexer2 "0.0.2"
|
||||
|
||||
mustache@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
|
||||
|
||||
mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
@@ -7586,7 +7614,7 @@ source-map@^0.4.2, source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
||||
@@ -8120,6 +8148,13 @@ uglify-js@^2.6:
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-js@^3.0.5:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
|
||||
dependencies:
|
||||
commander "~2.17.1"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -8336,6 +8371,12 @@ vinyl-source-stream@^2.0.0:
|
||||
through2 "^2.0.3"
|
||||
vinyl "^2.1.0"
|
||||
|
||||
vinyl-sourcemaps-apply@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705"
|
||||
dependencies:
|
||||
source-map "^0.5.1"
|
||||
|
||||
vinyl@^0.4.0:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847"
|
||||
|
||||
@@ -237,6 +237,12 @@
|
||||
<version>${mustache.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.sdorra</groupId>
|
||||
<artifactId>web-resources</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.sdorra</groupId>
|
||||
<artifactId>spotter-core</artifactId>
|
||||
@@ -515,7 +521,7 @@
|
||||
</systemProperty>
|
||||
<systemProperty>
|
||||
<name>sonia.scm.ui.proxy</name>
|
||||
<value>http://localhost:3000</value>
|
||||
<value>${livereload.proxy}</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
<webApp>
|
||||
@@ -547,6 +553,41 @@
|
||||
|
||||
<profiles>
|
||||
|
||||
<profile>
|
||||
<id>livereload</id>
|
||||
|
||||
<activation>
|
||||
<property>
|
||||
<name>livereload</name>
|
||||
</property>
|
||||
</activation>
|
||||
|
||||
<properties>
|
||||
<livereload.proxy>http://localhost:3000</livereload.proxy>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>ui-overlay</id>
|
||||
|
||||
<activation>
|
||||
<property>
|
||||
<name>!livereload</name>
|
||||
</property>
|
||||
</activation>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-ui</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package sonia.scm;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This dispatcher forwards every request to the index.html of the application.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ForwardingPushStateDispatcher implements PushStateDispatcher {
|
||||
@Override
|
||||
public void dispatch(HttpServletRequest request, HttpServletResponse response, String uri) throws IOException {
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.html");
|
||||
try {
|
||||
dispatcher.forward(request, response);
|
||||
} catch (ServletException e) {
|
||||
throw new IOException("failed to forward request", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package sonia.scm;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* Injection Provider for the {@link PushStateDispatcher}. The provider will return a {@link ProxyPushStateDispatcher}
|
||||
* if the system property {@code PushStateDispatcherProvider#PROPERTY_TARGET} is set to a proxy target url, otherwise
|
||||
* a {@link ForwardingPushStateDispatcher} is used.
|
||||
* a {@link TemplatingPushStateDispatcher} is used.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@@ -17,11 +18,18 @@ public class PushStateDispatcherProvider implements Provider<PushStateDispatcher
|
||||
@VisibleForTesting
|
||||
static final String PROPERTY_TARGET = "sonia.scm.ui.proxy";
|
||||
|
||||
private Provider<TemplatingPushStateDispatcher> templatingPushStateDispatcherProvider;
|
||||
|
||||
@Inject
|
||||
public PushStateDispatcherProvider(Provider<TemplatingPushStateDispatcher> templatingPushStateDispatcherProvider) {
|
||||
this.templatingPushStateDispatcherProvider = templatingPushStateDispatcherProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PushStateDispatcher get() {
|
||||
String target = System.getProperty(PROPERTY_TARGET);
|
||||
if (Strings.isNullOrEmpty(target)) {
|
||||
return new ForwardingPushStateDispatcher();
|
||||
return templatingPushStateDispatcherProvider.get();
|
||||
}
|
||||
return new ProxyPushStateDispatcher(target);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package sonia.scm;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import sonia.scm.template.Template;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* This dispatcher renders the /index.mustache template, which is merged in from the scm-ui package.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class TemplatingPushStateDispatcher implements PushStateDispatcher {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String TEMPLATE = "/index.mustache";
|
||||
|
||||
private final TemplateEngine templateEngine;
|
||||
|
||||
@Inject
|
||||
public TemplatingPushStateDispatcher(TemplateEngineFactory templateEngineFactory) {
|
||||
this(templateEngineFactory.getDefaultEngine());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TemplatingPushStateDispatcher(TemplateEngine templateEngine) {
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(HttpServletRequest request, HttpServletResponse response, String uri) throws IOException {
|
||||
response.setContentType("text/html");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
|
||||
Template template = templateEngine.getTemplate(TEMPLATE);
|
||||
try (Writer writer = response.getWriter()) {
|
||||
template.execute(writer, new IndexHtmlModel(request));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class IndexHtmlModel {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private IndexHtmlModel(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public String getContextPath() {
|
||||
return request.getContextPath();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package sonia.scm;
|
||||
|
||||
import com.github.sdorra.webresources.WebResourceSender;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.io.Resources;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.filter.WebElement;
|
||||
@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
@@ -27,6 +26,7 @@ import java.net.URL;
|
||||
@WebElement(value = WebResourceServlet.PATTERN, regex = true)
|
||||
public class WebResourceServlet extends HttpServlet {
|
||||
|
||||
|
||||
/**
|
||||
* exclude api requests and the old frontend servlets.
|
||||
*
|
||||
@@ -37,6 +37,11 @@ public class WebResourceServlet extends HttpServlet {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WebResourceServlet.class);
|
||||
|
||||
private final WebResourceSender sender = WebResourceSender.create()
|
||||
.withGZIP()
|
||||
.withGZIPMinLength(512)
|
||||
.withBufferSize(16384);
|
||||
|
||||
private final UberWebResourceLoader webResourceLoader;
|
||||
private final PushStateDispatcher pushStateDispatcher;
|
||||
|
||||
@@ -53,7 +58,7 @@ public class WebResourceServlet extends HttpServlet {
|
||||
LOG.trace("try to load {}", uri);
|
||||
URL url = webResourceLoader.getResource(uri);
|
||||
if (url != null) {
|
||||
serveResource(response, url);
|
||||
serveResource(request, response, url);
|
||||
} else {
|
||||
dispatch(request, response, uri);
|
||||
}
|
||||
@@ -72,10 +77,9 @@ public class WebResourceServlet extends HttpServlet {
|
||||
return HttpUtil.getStrippedURI(request);
|
||||
}
|
||||
|
||||
private void serveResource(HttpServletResponse response, URL url) {
|
||||
// TODO lastModifiedDate, if-... ???
|
||||
try (OutputStream output = response.getOutputStream()) {
|
||||
Resources.copy(url, output);
|
||||
private void serveResource(HttpServletRequest request, HttpServletResponse response, URL url) {
|
||||
try {
|
||||
sender.resource(url).send(request, response);
|
||||
} catch (IOException ex) {
|
||||
LOG.warn("failed to serve resource: {}", url);
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.api.rest.StatusExceptionMapper;
|
||||
import sonia.scm.util.CRLFInjectionException;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class CRLFInjectionExceptionMapper extends StatusExceptionMapper<CRLFInjectionException> {
|
||||
|
||||
public CRLFInjectionExceptionMapper() {
|
||||
super(CRLFInjectionException.class, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,12 @@ import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ChangesetCollectionToDtoMapper extends BasicCollectionToDtoMapper<Changeset, ChangesetDto, ChangesetToChangesetDtoMapper> {
|
||||
|
||||
private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper;
|
||||
private final ResourceLinks resourceLinks;
|
||||
protected final ResourceLinks resourceLinks;
|
||||
|
||||
@Inject
|
||||
public ChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
@@ -20,10 +21,14 @@ public class ChangesetCollectionToDtoMapper extends BasicCollectionToDtoMapper<C
|
||||
}
|
||||
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository) {
|
||||
return super.map(pageNumber, pageSize, pageResult, createSelfLink(repository), Optional.empty(), changeset -> changesetToChangesetDtoMapper.map(changeset, repository));
|
||||
return this.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository));
|
||||
}
|
||||
|
||||
private String createSelfLink(Repository repository) {
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, Supplier<String> selfLinkSupplier) {
|
||||
return super.map(pageNumber, pageSize, pageResult, selfLinkSupplier.get(), Optional.empty(), changeset -> changesetToChangesetDtoMapper.map(changeset, repository));
|
||||
}
|
||||
|
||||
protected String createSelfLink(Repository repository) {
|
||||
return resourceLinks.changeset().all(repository.getNamespace(), repository.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,71 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
public class DiffRootResource {
|
||||
|
||||
public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
|
||||
private final RepositoryServiceFactory serviceFactory;
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
public Response getAll(@DefaultValue("0") @QueryParam("page") int page,
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize,
|
||||
@QueryParam("sortBy") String sortBy,
|
||||
@DefaultValue("false") @QueryParam("desc") boolean desc) {
|
||||
throw new UnsupportedOperationException();
|
||||
@Inject
|
||||
public DiffRootResource(RepositoryServiceFactory serviceFactory) {
|
||||
this.serviceFactory = serviceFactory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the repository diff of a revision
|
||||
*
|
||||
* @param namespace repository namespace
|
||||
* @param name repository name
|
||||
* @param revision the revision
|
||||
* @return the dif of the revision
|
||||
* @throws NotFoundException if the repository is not found
|
||||
*/
|
||||
@GET
|
||||
@Path("{id}")
|
||||
public Response get(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
@Path("{revision}")
|
||||
@Produces(VndMediaType.DIFF)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "Bad Request"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the diff"),
|
||||
@ResponseCode(code = 404, condition = "not found, no revision with the specified param for the repository available or repository not found"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws NotFoundException {
|
||||
HttpUtil.checkForCRLFInjection(revision);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
StreamingOutput responseEntry = output -> {
|
||||
try {
|
||||
repositoryService.getDiffCommand()
|
||||
.setRevision(revision)
|
||||
.retriveContent(output);
|
||||
} catch (RevisionNotFoundException e) {
|
||||
throw new WebApplicationException(Response.Status.NOT_FOUND);
|
||||
}
|
||||
};
|
||||
return Response.ok(responseEntry)
|
||||
.header(HEADER_CONTENT_DISPOSITION, HttpUtil.createContentDispositionAttachmentHeader(String.format("%s-%s.diff", name, revision)))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class FileHistoryCollectionToDtoMapper extends ChangesetCollectionToDtoMapper {
|
||||
|
||||
|
||||
@Inject
|
||||
public FileHistoryCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
super(changesetToChangesetDtoMapper, resourceLinks);
|
||||
}
|
||||
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, String revision, String path) {
|
||||
return super.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository, revision, path));
|
||||
}
|
||||
|
||||
protected String createSelfLink(Repository repository, String revision, String path) {
|
||||
return super.resourceLinks.fileHistory().self(repository.getNamespace(), repository.getName(), revision, path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
|
||||
@Slf4j
|
||||
public class FileHistoryRootResource {
|
||||
|
||||
private final RepositoryServiceFactory serviceFactory;
|
||||
|
||||
private final FileHistoryCollectionToDtoMapper fileHistoryCollectionToDtoMapper;
|
||||
|
||||
|
||||
@Inject
|
||||
public FileHistoryRootResource(RepositoryServiceFactory serviceFactory, FileHistoryCollectionToDtoMapper fileHistoryCollectionToDtoMapper) {
|
||||
this.serviceFactory = serviceFactory;
|
||||
this.fileHistoryCollectionToDtoMapper = fileHistoryCollectionToDtoMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all changesets related to the given file starting with the given revision
|
||||
*
|
||||
* @param namespace the repository namespace
|
||||
* @param name the repository name
|
||||
* @param revision the revision
|
||||
* @param path the path of the file
|
||||
* @param page pagination
|
||||
* @param pageSize pagination
|
||||
* @return all changesets related to the given file starting with the given revision
|
||||
* @throws IOException on io error
|
||||
* @throws RevisionNotFoundException on missing revision
|
||||
* @throws RepositoryNotFoundException on missing repository
|
||||
*/
|
||||
@GET
|
||||
@Path("{revision}/{path: .*}")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the changeset"),
|
||||
@ResponseCode(code = 404, condition = "not found, no changesets available in the repository"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
||||
@TypeHint(CollectionDto.class)
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name,
|
||||
@PathParam("revision") String revision,
|
||||
@PathParam("path") String path,
|
||||
@DefaultValue("0") @QueryParam("page") int page,
|
||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException, RevisionNotFoundException, RepositoryNotFoundException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
log.info("Get changesets of the file {} and revision {}", path, revision);
|
||||
Repository repository = repositoryService.getRepository();
|
||||
ChangesetPagingResult changesets = repositoryService.getLogCommand()
|
||||
.setPagingStart(page)
|
||||
.setPagingLimit(pageSize)
|
||||
.setPath(path)
|
||||
.setStartChangeset(revision)
|
||||
.getChangesets();
|
||||
if (changesets != null && changesets.getChangesets() != null) {
|
||||
PageResult<Changeset> pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal());
|
||||
return Response.ok(fileHistoryCollectionToDtoMapper.map(page, pageSize, pageResult, repository, revision, path)).build();
|
||||
} else {
|
||||
String message = String.format("for the revision %s and the file %s there is no changesets", revision, path);
|
||||
log.error(message);
|
||||
throw new InternalRepositoryException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import sonia.scm.repository.SubRepository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static de.otto.edison.hal.Link.link;
|
||||
|
||||
@Mapper
|
||||
public abstract class FileObjectToFileObjectDtoMapper extends BaseMapper<FileObject, FileObjectDto> {
|
||||
|
||||
@@ -29,6 +31,7 @@ public abstract class FileObjectToFileObjectDtoMapper extends BaseMapper<FileObj
|
||||
links.self(resourceLinks.source().sourceWithPath(namespaceAndName.getNamespace(), namespaceAndName.getName(), revision, path));
|
||||
} else {
|
||||
links.self(resourceLinks.source().content(namespaceAndName.getNamespace(), namespaceAndName.getName(), revision, path));
|
||||
links.single(link("history", resourceLinks.fileHistory().self(namespaceAndName.getNamespace(), namespaceAndName.getName(), revision, path)));
|
||||
}
|
||||
|
||||
dto.add(links.build());
|
||||
|
||||
@@ -41,6 +41,7 @@ public class RepositoryResource {
|
||||
private final Provider<PermissionRootResource> permissionRootResource;
|
||||
private final Provider<DiffRootResource> diffRootResource;
|
||||
private final Provider<ModificationsRootResource> modificationsRootResource;
|
||||
private final Provider<FileHistoryRootResource> fileHistoryRootResource;
|
||||
|
||||
@Inject
|
||||
public RepositoryResource(
|
||||
@@ -51,7 +52,10 @@ public class RepositoryResource {
|
||||
Provider<ChangesetRootResource> changesetRootResource,
|
||||
Provider<SourceRootResource> sourceRootResource, Provider<ContentResource> contentResource,
|
||||
Provider<PermissionRootResource> permissionRootResource,
|
||||
Provider<DiffRootResource> diffRootResource, Provider<ModificationsRootResource> modificationsRootResource) {
|
||||
Provider<DiffRootResource> diffRootResource,
|
||||
Provider<ModificationsRootResource> modificationsRootResource,
|
||||
Provider<FileHistoryRootResource> fileHistoryRootResource
|
||||
) {
|
||||
this.dtoToRepositoryMapper = dtoToRepositoryMapper;
|
||||
this.manager = manager;
|
||||
this.repositoryToDtoMapper = repositoryToDtoMapper;
|
||||
@@ -64,6 +68,7 @@ public class RepositoryResource {
|
||||
this.permissionRootResource = permissionRootResource;
|
||||
this.diffRootResource = diffRootResource;
|
||||
this.modificationsRootResource = modificationsRootResource;
|
||||
this.fileHistoryRootResource = fileHistoryRootResource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,6 +172,11 @@ public class RepositoryResource {
|
||||
return changesetRootResource.get();
|
||||
}
|
||||
|
||||
@Path("history/")
|
||||
public FileHistoryRootResource history() {
|
||||
return fileHistoryRootResource.get();
|
||||
}
|
||||
|
||||
@Path("sources/")
|
||||
public SourceRootResource sources() {
|
||||
return sourceRootResource.get();
|
||||
|
||||
@@ -15,6 +15,10 @@ class ResourceLinks {
|
||||
this.uriInfoStore = uriInfoStore;
|
||||
}
|
||||
|
||||
// we have to add the file path using URI, so that path separators (aka '/') will not be encoded as '%2F'
|
||||
private static String addPath(String sourceWithPath, String path) {
|
||||
return URI.create(sourceWithPath).resolve(path).toASCIIString();
|
||||
}
|
||||
|
||||
GroupLinks group() {
|
||||
return new GroupLinks(uriInfoStore.get());
|
||||
@@ -322,6 +326,23 @@ class ResourceLinks {
|
||||
}
|
||||
}
|
||||
|
||||
public FileHistoryLinks fileHistory() {
|
||||
return new FileHistoryLinks(uriInfoStore.get());
|
||||
}
|
||||
|
||||
static class FileHistoryLinks {
|
||||
private final LinkBuilder fileHistoryLinkBuilder;
|
||||
|
||||
FileHistoryLinks(UriInfo uriInfo) {
|
||||
fileHistoryLinkBuilder = new LinkBuilder(uriInfo, RepositoryRootResource.class, RepositoryResource.class, FileHistoryRootResource.class);
|
||||
}
|
||||
|
||||
String self(String namespace, String name, String changesetId, String path) {
|
||||
return addPath(fileHistoryLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("history").parameters().method("getAll").parameters(changesetId, "").href(), path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SourceLinks source() {
|
||||
return new SourceLinks(uriInfoStore.get());
|
||||
}
|
||||
@@ -353,10 +374,7 @@ class ResourceLinks {
|
||||
return addPath(sourceLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("content").parameters().method("get").parameters(revision, "").href(), path);
|
||||
}
|
||||
|
||||
// we have to add the file path using URI, so that path separators (aka '/') will not be encoded as '%2F'
|
||||
private String addPath(String sourceWithPath, String path) {
|
||||
return URI.create(sourceWithPath).resolve(path).toASCIIString();
|
||||
}
|
||||
|
||||
}
|
||||
public PermissionLinks permission() {
|
||||
return new PermissionLinks(uriInfoStore.get());
|
||||
|
||||
@@ -31,18 +31,11 @@
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -55,47 +48,27 @@ import java.nio.file.Path;
|
||||
public class PathWebResourceLoader implements WebResourceLoader
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String DEFAULT_SEPARATOR = "/";
|
||||
private static final String SEPARATOR = "/";
|
||||
|
||||
/**
|
||||
* the logger for PathWebResourceLoader
|
||||
*/
|
||||
private static final Logger logger =
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(PathWebResourceLoader.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param directory
|
||||
*/
|
||||
public PathWebResourceLoader(Path directory)
|
||||
{
|
||||
this.directory = directory;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public URL getResource(String path)
|
||||
{
|
||||
public URL getResource(String path) {
|
||||
URL resource = null;
|
||||
Path file = directory.resolve(filePath(path));
|
||||
|
||||
if (Files.exists(file) && ! Files.isDirectory(file))
|
||||
{
|
||||
logger.trace("found path {} at {}", path, file);
|
||||
LOG.trace("found path {} at {}", path, file);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -103,56 +76,20 @@ public class PathWebResourceLoader implements WebResourceLoader
|
||||
}
|
||||
catch (MalformedURLException ex)
|
||||
{
|
||||
logger.error("could not transform path to url", ex);
|
||||
LOG.error("could not transform path to url", ex);
|
||||
}
|
||||
} else {
|
||||
LOG.trace("could not find file {}", file);
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String filePath(String path)
|
||||
{
|
||||
|
||||
// TODO handle illegal path parts, such as ..
|
||||
String filePath = filePath(DEFAULT_SEPARATOR, path);
|
||||
|
||||
if (!DEFAULT_SEPARATOR.equals(File.separator))
|
||||
{
|
||||
filePath = filePath(File.separator, path);
|
||||
private String filePath(String path) {
|
||||
if (path.startsWith(SEPARATOR)) {
|
||||
return path.substring(1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param separator
|
||||
* @param path
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String filePath(String separator, String path)
|
||||
{
|
||||
String filePath = path;
|
||||
|
||||
if (filePath.startsWith(separator))
|
||||
{
|
||||
filePath = filePath.substring(separator.length());
|
||||
}
|
||||
|
||||
return filePath;
|
||||
return path;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,51 +0,0 @@
|
||||
package sonia.scm;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ForwardingPushStateDispatcherTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private RequestDispatcher requestDispatcher;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
private ForwardingPushStateDispatcher dispatcher = new ForwardingPushStateDispatcher();
|
||||
|
||||
@Test
|
||||
public void testDispatch() throws ServletException, IOException {
|
||||
when(request.getRequestDispatcher("/index.html")).thenReturn(requestDispatcher);
|
||||
|
||||
dispatcher.dispatch(request, response, "/something");
|
||||
|
||||
verify(requestDispatcher).forward(request, response);
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void testWrapServletException() throws ServletException, IOException {
|
||||
when(request.getRequestDispatcher("/index.html")).thenReturn(requestDispatcher);
|
||||
doThrow(ServletException.class).when(requestDispatcher).forward(request, response);
|
||||
|
||||
dispatcher.dispatch(request, response, "/something");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,23 @@
|
||||
package sonia.scm;
|
||||
|
||||
import com.google.inject.util.Providers;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PushStateDispatcherProviderTest {
|
||||
|
||||
private PushStateDispatcherProvider provider = new PushStateDispatcherProvider();
|
||||
@Mock
|
||||
private TemplateEngine templateEngine;
|
||||
|
||||
private PushStateDispatcherProvider provider = new PushStateDispatcherProvider(
|
||||
Providers.of(new TemplatingPushStateDispatcher(templateEngine))
|
||||
);
|
||||
|
||||
@Test
|
||||
public void testGetProxyPushStateWithPropertySet() {
|
||||
@@ -20,7 +29,7 @@ public class PushStateDispatcherProviderTest {
|
||||
@Test
|
||||
public void testGetProxyPushStateWithoutProperty() {
|
||||
PushStateDispatcher dispatcher = provider.get();
|
||||
Assertions.assertThat(dispatcher).isInstanceOf(ForwardingPushStateDispatcher.class);
|
||||
Assertions.assertThat(dispatcher).isInstanceOf(TemplatingPushStateDispatcher.class);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package sonia.scm;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.template.Template;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TemplatingPushStateDispatcherTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Mock
|
||||
private TemplateEngine templateEngine;
|
||||
|
||||
@Mock
|
||||
private Template template;
|
||||
|
||||
private TemplatingPushStateDispatcher dispatcher;
|
||||
|
||||
@Before
|
||||
public void setUpMocks() {
|
||||
dispatcher = new TemplatingPushStateDispatcher(templateEngine);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDispatch() throws IOException {
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
when(templateEngine.getTemplate(TemplatingPushStateDispatcher.TEMPLATE)).thenReturn(template);
|
||||
|
||||
when(response.getWriter()).thenReturn(new PrintWriter(new StringWriter()));
|
||||
|
||||
dispatcher.dispatch(request, response, "/someurl");
|
||||
|
||||
verify(response).setContentType("text/html");
|
||||
verify(response).setCharacterEncoding("UTF-8");
|
||||
|
||||
ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
|
||||
|
||||
verify(template).execute(any(Writer.class), captor.capture());
|
||||
|
||||
TemplatingPushStateDispatcher.IndexHtmlModel model = (TemplatingPushStateDispatcher.IndexHtmlModel) captor.getValue();
|
||||
assertEquals("/scm", model.getContextPath());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,10 +19,17 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class WebResourceServletTest {
|
||||
|
||||
@Rule
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
public class BaseRepositoryTest {
|
||||
|
||||
|
||||
protected RepositoryToRepositoryDtoMapper repositoryToDtoMapper;
|
||||
protected RepositoryDtoToRepositoryMapper dtoToRepositoryMapper;
|
||||
protected RepositoryManager manager;
|
||||
protected Provider<TagRootResource> tagRootResource;
|
||||
protected Provider<BranchRootResource> branchRootResource;
|
||||
protected Provider<ChangesetRootResource> changesetRootResource;
|
||||
protected Provider<SourceRootResource> sourceRootResource;
|
||||
protected Provider<ContentResource> contentResource;
|
||||
protected Provider<PermissionRootResource> permissionRootResource;
|
||||
protected Provider<DiffRootResource> diffRootResource;
|
||||
protected Provider<ModificationsRootResource> modificationsRootResource;
|
||||
protected Provider<FileHistoryRootResource> fileHistoryRootResource;
|
||||
protected Provider<RepositoryCollectionResource> repositoryCollectionResource;
|
||||
|
||||
|
||||
RepositoryRootResource getRepositoryRootResource() {
|
||||
return new RepositoryRootResource(MockProvider.of(new RepositoryResource(
|
||||
repositoryToDtoMapper,
|
||||
dtoToRepositoryMapper,
|
||||
manager,
|
||||
tagRootResource,
|
||||
branchRootResource,
|
||||
changesetRootResource,
|
||||
sourceRootResource,
|
||||
contentResource,
|
||||
permissionRootResource,
|
||||
diffRootResource,
|
||||
modificationsRootResource,
|
||||
fileHistoryRootResource)), repositoryCollectionResource);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@Slf4j
|
||||
public class BranchRootResourceTest {
|
||||
public class BranchRootResourceTest extends BaseRepositoryTest {
|
||||
|
||||
public static final String BRANCH_PATH = "space/repo/branches/master";
|
||||
public static final String BRANCH_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + BRANCH_PATH;
|
||||
@@ -92,9 +92,8 @@ public class BranchRootResourceTest {
|
||||
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||
BranchCollectionToDtoMapper branchCollectionToDtoMapper = new BranchCollectionToDtoMapper(branchToDtoMapper, resourceLinks);
|
||||
branchRootResource = new BranchRootResource(serviceFactory, branchToDtoMapper, branchCollectionToDtoMapper, changesetCollectionToDtoMapper);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider.of(new RepositoryResource(null, null, null, null, MockProvider.of(branchRootResource), null, null, null, null, null, null)), null);
|
||||
dispatcher.getRegistry().addSingletonResource(repositoryRootResource);
|
||||
|
||||
super.branchRootResource = MockProvider.of(branchRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
|
||||
@@ -44,7 +44,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@Slf4j
|
||||
public class ChangesetRootResourceTest {
|
||||
public class ChangesetRootResourceTest extends BaseRepositoryTest{
|
||||
|
||||
|
||||
public static final String CHANGESET_PATH = "space/repo/changesets/";
|
||||
@@ -79,10 +79,8 @@ public class ChangesetRootResourceTest {
|
||||
public void prepareEnvironment() throws Exception {
|
||||
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||
changesetRootResource = new ChangesetRootResource(serviceFactory, changesetCollectionToDtoMapper, changesetToChangesetDtoMapper);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider
|
||||
.of(new RepositoryResource(null, null, null, null, null,
|
||||
MockProvider.of(changesetRootResource), null, null, null, null, null)), null);
|
||||
dispatcher.getRegistry().addSingletonResource(repositoryRootResource);
|
||||
super.changesetRootResource = MockProvider.of(changesetRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
|
||||
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
@@ -125,7 +123,6 @@ public class ChangesetRootResourceTest {
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", authorName)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"mail\":\"%s\"", authorEmail)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -155,7 +152,6 @@ public class ChangesetRootResourceTest {
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", authorName)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"mail\":\"%s\"", authorEmail)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.subject.support.SubjectThreadState;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.DiffCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@Slf4j
|
||||
public class DiffResourceTest extends BaseRepositoryTest {
|
||||
|
||||
|
||||
public static final String DIFF_PATH = "space/repo/diff/";
|
||||
public static final String DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + DIFF_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
@Mock
|
||||
private RepositoryServiceFactory serviceFactory;
|
||||
|
||||
@Mock
|
||||
private RepositoryService service;
|
||||
|
||||
@Mock
|
||||
private DiffCommandBuilder diffCommandBuilder;
|
||||
|
||||
private DiffRootResource diffRootResource;
|
||||
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
diffRootResource = new DiffRootResource(serviceFactory);
|
||||
super.diffRootResource = MockProvider.of(diffRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(CRLFInjectionExceptionMapper.class);
|
||||
when(service.getDiffCommand()).thenReturn(diffCommandBuilder);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
when(subject.isPermitted(any(String.class))).thenReturn(true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupContext() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetDiffs() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenReturn(diffCommandBuilder);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
log.info("Response :{}", response.getContentAsString());
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(200);
|
||||
assertThat(response.getContentAsString())
|
||||
.isNotNull();
|
||||
String expectedHeader = "Content-Disposition";
|
||||
String expectedValue = "attachment; filename=\"repo-revision.diff\"; filename*=utf-8''repo-revision.diff";
|
||||
assertThat(response.getOutputHeaders().containsKey(expectedHeader)).isTrue();
|
||||
assertThat((String) response.getOutputHeaders().get("Content-Disposition").get(0))
|
||||
.contains(expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(RepositoryNotFoundException.class);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRevision() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenThrow(RevisionNotFoundException.class);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400OnCrlfInjection() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenThrow(RevisionNotFoundException.class);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "ny%0D%0ASet-cookie:%20Tamper=3079675143472450634")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@ public class DispatcherMock {
|
||||
dispatcher.getProviderFactory().registerProvider(AlreadyExistsExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(ConcurrentModificationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.subject.support.SubjectThreadState;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.LogCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@Slf4j
|
||||
public class FileHistoryResourceTest extends BaseRepositoryTest {
|
||||
|
||||
public static final String FILE_HISTORY_PATH = "space/repo/history/";
|
||||
public static final String FILE_HISTORY_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + FILE_HISTORY_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
|
||||
@Mock
|
||||
private RepositoryServiceFactory serviceFactory;
|
||||
|
||||
@Mock
|
||||
private RepositoryService service;
|
||||
|
||||
@Mock
|
||||
private LogCommandBuilder logCommandBuilder;
|
||||
|
||||
private FileHistoryCollectionToDtoMapper fileHistoryCollectionToDtoMapper;
|
||||
|
||||
@InjectMocks
|
||||
private ChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
||||
|
||||
private FileHistoryRootResource fileHistoryRootResource;
|
||||
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
fileHistoryCollectionToDtoMapper = new FileHistoryCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||
fileHistoryRootResource = new FileHistoryRootResource(serviceFactory, fileHistoryCollectionToDtoMapper);
|
||||
super.fileHistoryRootResource = MockProvider.of(fileHistoryRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
when(service.getLogCommand()).thenReturn(logCommandBuilder);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
when(subject.isPermitted(any(String.class))).thenReturn(true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupContext() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetFileHistory() throws Exception {
|
||||
String id = "revision_123";
|
||||
String path = "root_dir/sub_dir/file-to-inspect.txt";
|
||||
Instant creationDate = Instant.now();
|
||||
String authorName = "name";
|
||||
String authorEmail = "em@i.l";
|
||||
String commit = "my branch commit";
|
||||
ChangesetPagingResult changesetPagingResult = mock(ChangesetPagingResult.class);
|
||||
List<Changeset> changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit));
|
||||
when(changesetPagingResult.getChangesets()).thenReturn(changesetList);
|
||||
when(changesetPagingResult.getTotal()).thenReturn(1);
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
log.info("Response :{}", response.getContentAsString());
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"id\":\"%s\"", id)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", authorName)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"mail\":\"%s\"", authorEmail)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(RepositoryNotFoundException.class);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + "revision/a.txt")
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRevision() throws Exception {
|
||||
String id = "revision_123";
|
||||
String path = "root_dir/sub_dir/file-to-inspect.txt";
|
||||
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(RevisionNotFoundException.class);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet500OnInternalRepositoryException() throws Exception {
|
||||
String id = "revision_123";
|
||||
String path = "root_dir/sub_dir/file-to-inspect.txt";
|
||||
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(InternalRepositoryException.class);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet500OnNullChangesets() throws Exception {
|
||||
String id = "revision_123";
|
||||
String path = "root_dir/sub_dir/file-to-inspect.txt";
|
||||
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(null);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(500, response.getStatus());
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@Slf4j
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class ModificationsResourceTest {
|
||||
public class ModificationsResourceTest extends BaseRepositoryTest {
|
||||
|
||||
|
||||
public static final String MODIFICATIONS_PATH = "space/repo/modifications/";
|
||||
@@ -71,10 +71,8 @@ public class ModificationsResourceTest {
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
modificationsRootResource = new ModificationsRootResource(serviceFactory, modificationsToDtoMapper);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider
|
||||
.of(new RepositoryResource(null, null, null, null, null,
|
||||
null, null, null, null, null, MockProvider.of(modificationsRootResource))), null);
|
||||
dispatcher.getRegistry().addSingletonResource(repositoryRootResource);
|
||||
super.modificationsRootResource = MockProvider.of(modificationsRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
|
||||
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
|
||||
@@ -64,7 +64,7 @@ import static sonia.scm.api.v2.resources.PermissionDto.GROUP_PREFIX;
|
||||
password = "secret",
|
||||
configuration = "classpath:sonia/scm/repository/shiro.ini"
|
||||
)
|
||||
public class PermissionRootResourceTest {
|
||||
public class PermissionRootResourceTest extends BaseRepositoryTest {
|
||||
private static final String REPOSITORY_NAMESPACE = "repo_namespace";
|
||||
private static final String REPOSITORY_NAME = "repo";
|
||||
private static final String PERMISSION_WRITE = "repository:permissionWrite:" + REPOSITORY_NAME;
|
||||
@@ -137,9 +137,8 @@ public class PermissionRootResourceTest {
|
||||
initMocks(this);
|
||||
permissionCollectionToDtoMapper = new PermissionCollectionToDtoMapper(permissionToPermissionDtoMapper, resourceLinks);
|
||||
permissionRootResource = new PermissionRootResource(permissionDtoToPermissionMapper, permissionToPermissionDtoMapper, permissionCollectionToDtoMapper, resourceLinks, repositoryManager);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider
|
||||
.of(new RepositoryResource(null, null, null, null, null, null, null, null, MockProvider.of(permissionRootResource), null, null)), null);
|
||||
dispatcher = createDispatcher(repositoryRootResource);
|
||||
super.permissionRootResource = MockProvider.of(permissionRootResource);
|
||||
dispatcher = createDispatcher(getRepositoryRootResource());
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
password = "secret",
|
||||
configuration = "classpath:sonia/scm/repository/shiro.ini"
|
||||
)
|
||||
public class RepositoryRootResourceTest {
|
||||
public class RepositoryRootResourceTest extends BaseRepositoryTest {
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
@@ -79,11 +79,12 @@ public class RepositoryRootResourceTest {
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
RepositoryResource repositoryResource = new RepositoryResource(repositoryToDtoMapper, dtoToRepositoryMapper, repositoryManager, null, null, null, null, null, null, null, null);
|
||||
super.repositoryToDtoMapper = repositoryToDtoMapper;
|
||||
super.dtoToRepositoryMapper = dtoToRepositoryMapper;
|
||||
super.manager = repositoryManager;
|
||||
RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks);
|
||||
RepositoryCollectionResource repositoryCollectionResource = new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider.of(repositoryResource), MockProvider.of(repositoryCollectionResource));
|
||||
dispatcher = createDispatcher(repositoryRootResource);
|
||||
super.repositoryCollectionResource = MockProvider.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks));
|
||||
dispatcher = createDispatcher(getRepositoryRootResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,6 +22,7 @@ public class ResourceLinksMock {
|
||||
when(resourceLinks.tag()).thenReturn(new ResourceLinks.TagCollectionLinks(uriInfo));
|
||||
when(resourceLinks.branchCollection()).thenReturn(new ResourceLinks.BranchCollectionLinks(uriInfo));
|
||||
when(resourceLinks.changeset()).thenReturn(new ResourceLinks.ChangesetLinks(uriInfo));
|
||||
when(resourceLinks.fileHistory()).thenReturn(new ResourceLinks.FileHistoryLinks(uriInfo));
|
||||
when(resourceLinks.source()).thenReturn(new ResourceLinks.SourceLinks(uriInfo));
|
||||
when(resourceLinks.permission()).thenReturn(new ResourceLinks.PermissionLinks(uriInfo));
|
||||
when(resourceLinks.config()).thenReturn(new ResourceLinks.ConfigLinks(uriInfo));
|
||||
|
||||
@@ -32,7 +32,7 @@ import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class SourceRootResourceTest {
|
||||
public class SourceRootResourceTest extends BaseRepositoryTest {
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
private final URI baseUri = URI.create("/");
|
||||
@@ -63,20 +63,8 @@ public class SourceRootResourceTest {
|
||||
|
||||
when(fileObjectToFileObjectDtoMapper.map(any(FileObject.class), any(NamespaceAndName.class), anyString())).thenReturn(dto);
|
||||
SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToBrowserResultDtoMapper);
|
||||
RepositoryRootResource repositoryRootResource =
|
||||
new RepositoryRootResource(MockProvider.of(new RepositoryResource(null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
MockProvider.of(sourceRootResource),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)),
|
||||
null);
|
||||
dispatcher = createDispatcher(repositoryRootResource);
|
||||
super.sourceRootResource = MockProvider.of(sourceRootResource);
|
||||
dispatcher = createDispatcher(getRepositoryRootResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
@@ -35,14 +34,15 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
|
||||
@Slf4j
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class TagRootResourceTest {
|
||||
public class TagRootResourceTest extends BaseRepositoryTest {
|
||||
|
||||
public static final String TAG_PATH = "space/repo/tags/";
|
||||
public static final String TAG_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + TAG_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
private Dispatcher dispatcher ;
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
@@ -72,10 +72,8 @@ public class TagRootResourceTest {
|
||||
public void prepareEnvironment() throws Exception {
|
||||
tagCollectionToDtoMapper = new TagCollectionToDtoMapper(resourceLinks, tagToTagDtoMapper);
|
||||
tagRootResource = new TagRootResource(serviceFactory, tagCollectionToDtoMapper, tagToTagDtoMapper);
|
||||
RepositoryRootResource repositoryRootResource = new RepositoryRootResource(MockProvider
|
||||
.of(new RepositoryResource(null, null, null, MockProvider.of(tagRootResource), null,
|
||||
null, null, null, null, null, null)), null);
|
||||
dispatcher.getRegistry().addSingletonResource(repositoryRootResource);
|
||||
super.tagRootResource = MockProvider.of(tagRootResource);
|
||||
dispatcher = createDispatcher(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
|
||||
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
|
||||
Reference in New Issue
Block a user