This commit is contained in:
René Pfeuffer
2018-11-06 09:26:41 +01:00
119 changed files with 8479 additions and 5472 deletions

View File

@@ -757,7 +757,7 @@
<guice.version>4.0</guice.version>
<!-- event bus -->
<legman.version>1.3.0</legman.version>
<legman.version>1.4.0</legman.version>
<!-- webserver -->
<jetty.version>9.2.10.v20150310</jetty.version>

View File

@@ -33,33 +33,30 @@
package sonia.scm;
import java.util.Collections;
/**
*
* @author Sebastian Sdorra
* @version 1.6
*/
public class NotSupportedFeatureException extends Exception
{
public class NotSupportedFeatureException extends ExceptionWithContext {
/** Field description */
private static final long serialVersionUID = 256498734456613496L;
//~--- constructors ---------------------------------------------------------
private static final String CODE = "9SR8G0kmU1";
/**
* Constructs ...
*
*/
public NotSupportedFeatureException() {}
/**
* Constructs ...
*
*
* @param message
*/
public NotSupportedFeatureException(String message)
public NotSupportedFeatureException(String feature)
{
super(message);
super(Collections.emptyList(),createMessage(feature));
}
@Override
public String getCode() {
return CODE;
}
private static String createMessage(String feature) {
return "feature " + feature + " is not supported by this repository";
}
}

View File

@@ -170,8 +170,7 @@ public abstract class AbstractRepositoryHandler<C extends RepositoryConfig>
@Override
public ImportHandler getImportHandler() throws NotSupportedFeatureException
{
throw new NotSupportedFeatureException(
"import handler is not supported by this repository handler");
throw new NotSupportedFeatureException("import");
}
/**

View File

@@ -80,13 +80,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>

View File

@@ -0,0 +1,265 @@
package sonia.scm.it;
import org.apache.http.HttpStatus;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import sonia.scm.it.utils.RepositoryUtil;
import sonia.scm.it.utils.ScmRequests;
import sonia.scm.it.utils.TestData;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.client.api.RepositoryClient;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static sonia.scm.it.utils.RestUtil.ADMIN_PASSWORD;
import static sonia.scm.it.utils.RestUtil.ADMIN_USERNAME;
public class DiffITCase {
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
private RepositoryClient svnRepositoryClient;
private RepositoryClient gitRepositoryClient;
private RepositoryClient hgRepositoryClient;
private ScmRequests.RepositoryResponse<ScmRequests.IndexResponse> svnRepositoryResponse;
private ScmRequests.RepositoryResponse<ScmRequests.IndexResponse> hgRepositoryResponse;
private ScmRequests.RepositoryResponse<ScmRequests.IndexResponse> gitRepositoryResponse;
private File svnFolder;
private File gitFolder;
private File hgFolder;
@Before
public void init() throws IOException {
TestData.createDefault();
String namespace = ADMIN_USERNAME;
String repo = TestData.getDefaultRepoName("svn");
svnRepositoryResponse =
ScmRequests.start()
.requestIndexResource(ADMIN_USERNAME, ADMIN_PASSWORD)
.requestRepository(namespace, repo)
.assertStatusCode(HttpStatus.SC_OK);
svnFolder = tempFolder.newFolder("svn");
svnRepositoryClient = RepositoryUtil.createRepositoryClient("svn", svnFolder);
repo = TestData.getDefaultRepoName("git");
gitRepositoryResponse =
ScmRequests.start()
.requestIndexResource(ADMIN_USERNAME, ADMIN_PASSWORD)
.requestRepository(namespace, repo)
.assertStatusCode(HttpStatus.SC_OK);
gitFolder = tempFolder.newFolder("git");
gitRepositoryClient = RepositoryUtil.createRepositoryClient("git", gitFolder);
repo = TestData.getDefaultRepoName("hg");
hgRepositoryResponse =
ScmRequests.start()
.requestIndexResource(ADMIN_USERNAME, ADMIN_PASSWORD)
.requestRepository(namespace, repo)
.assertStatusCode(HttpStatus.SC_OK);
hgFolder = tempFolder.newFolder("hg");
hgRepositoryClient = RepositoryUtil.createRepositoryClient("hg", hgFolder);
}
@Test
public void shouldFindDiffsInGitFormat() throws IOException {
String svnDiff = getDiff(RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a"), svnRepositoryResponse);
String gitDiff = getDiff(RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a"), gitRepositoryResponse);
String hgDiff = getDiff(RepositoryUtil.createAndCommitFile(hgRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a"), hgRepositoryResponse);
assertThat(Lists.newArrayList(svnDiff, gitDiff, hgDiff))
.allSatisfy(diff -> assertThat(diff)
.contains("diff --git "));
}
@Test
public void svnAddFileDiffShouldBeConvertedToGitDiff() throws IOException {
String svnDiff = getDiff(RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a"), svnRepositoryResponse);
String gitDiff = getDiff(RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a"), gitRepositoryResponse);
String expected = getGitDiffWithoutIndexLine(gitDiff);
assertThat(svnDiff)
.isEqualTo(expected);
}
@Test
public void svnDeleteFileDiffShouldBeConvertedToGitDiff() throws IOException {
RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a");
RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a");
String svnDiff = getDiff(RepositoryUtil.removeAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt"), svnRepositoryResponse);
String gitDiff = getDiff(RepositoryUtil.removeAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt"), gitRepositoryResponse);
String expected = getGitDiffWithoutIndexLine(gitDiff);
assertThat(svnDiff)
.isEqualTo(expected);
}
@Test
public void svnUpdateFileDiffShouldBeConvertedToGitDiff() throws IOException {
RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a");
RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt", "content of a");
String svnDiff = getDiff(RepositoryUtil.updateAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, "a.txt", "the updated content of a"), svnRepositoryResponse);
String gitDiff = getDiff(RepositoryUtil.updateAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, "a.txt", "the updated content of a"), gitRepositoryResponse);
String expected = getGitDiffWithoutIndexLine(gitDiff);
assertThat(svnDiff)
.isEqualTo(expected);
}
@Test
public void svnMultipleChangesDiffShouldBeConvertedToGitDiff() throws IOException {
String svnDiff = getDiff(applyMultipleChanges(svnRepositoryClient, "fileToBeDeleted.txt", "fileToBeUpdated.txt", "addedFile.txt"), svnRepositoryResponse);
String gitDiff = getDiff(applyMultipleChanges(gitRepositoryClient, "fileToBeDeleted.txt", "fileToBeUpdated.txt", "addedFile.txt"), gitRepositoryResponse);
String endOfDiffPart = "\\ No newline at end of file\n";
String[] gitDiffs = gitDiff.split(endOfDiffPart);
List<String> expected = Arrays.stream(gitDiffs)
.map(this::getGitDiffWithoutIndexLine)
.collect(Collectors.toList());
assertThat(svnDiff.split(endOfDiffPart))
.containsExactlyInAnyOrderElementsOf(expected);
}
@Test
public void svnMultipleSubFolderChangesDiffShouldBeConvertedToGitDiff() throws IOException {
String svnDiff = getDiff(applyMultipleChanges(svnRepositoryClient, "a/b/fileToBeDeleted.txt", "a/c/fileToBeUpdated.txt", "a/d/addedFile.txt"), svnRepositoryResponse);
String gitDiff = getDiff(applyMultipleChanges(gitRepositoryClient, "a/b/fileToBeDeleted.txt", "a/c/fileToBeUpdated.txt", "a/d/addedFile.txt"), gitRepositoryResponse);
String endOfDiffPart = "\\ No newline at end of file\n";
String[] gitDiffs = gitDiff.split(endOfDiffPart);
List<String> expected = Arrays.stream(gitDiffs)
.map(this::getGitDiffWithoutIndexLine)
.collect(Collectors.toList());
assertThat(svnDiff.split(endOfDiffPart))
.containsExactlyInAnyOrderElementsOf(expected);
}
@Test
public void svnLargeChangesDiffShouldBeConvertedToGitDiff() throws IOException, URISyntaxException {
String fileName = "SvnDiffGenerator_forTest";
RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, fileName, "");
RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, fileName, "");
String fileContent = getFileContent("/diff/largefile/original/SvnDiffGenerator_forTest");
String svnDiff = getDiff(RepositoryUtil.updateAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, fileName, fileContent), svnRepositoryResponse);
String gitDiff = getDiff(RepositoryUtil.updateAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, fileName, fileContent), gitRepositoryResponse);
assertThat(svnDiff)
.isEqualTo(getGitDiffWithoutIndexLine(gitDiff));
fileContent = getFileContent("/diff/largefile/modified/v1/SvnDiffGenerator_forTest");
svnDiff = getDiff(RepositoryUtil.updateAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, fileName, fileContent), svnRepositoryResponse);
gitDiff = getDiff(RepositoryUtil.updateAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, fileName, fileContent), gitRepositoryResponse);
assertThat(svnDiff)
.isEqualTo(getGitDiffWithoutIndexLine(gitDiff));
fileContent = getFileContent("/diff/largefile/modified/v2/SvnDiffGenerator_forTest");
svnDiff = getDiff(RepositoryUtil.updateAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, fileName, fileContent), svnRepositoryResponse);
gitDiff = getDiff(RepositoryUtil.updateAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, fileName, fileContent), gitRepositoryResponse);
assertThat(svnDiff)
.isEqualTo(getGitDiffWithoutIndexLine(gitDiff));
}
/**
* FIXME: the binary Git Diff output is not GIT conform
*/
@Test
@Ignore
@SuppressWarnings("squid:S1607")
public void svnBinaryChangesDiffShouldBeConvertedToGitDiff() throws IOException, URISyntaxException {
String fileName = "binary";
File file = new File(svnRepositoryClient.getWorkingCopy(), fileName);
Files.copy(Paths.get(getClass().getResource("/diff/binaryfile/echo").toURI()), Paths.get(file.toURI()));
Changeset commit = RepositoryUtil.addFileAndCommit(svnRepositoryClient, fileName, ADMIN_USERNAME, "");
file = new File(gitRepositoryClient.getWorkingCopy(), fileName);
Files.copy(Paths.get(getClass().getResource("/diff/binaryfile/echo").toURI()), Paths.get(file.toURI()));
Changeset commit1 = RepositoryUtil.addFileAndCommit(gitRepositoryClient, fileName, ADMIN_USERNAME, "");
String svnDiff = getDiff(commit, svnRepositoryResponse);
String gitDiff = getDiff(commit1, gitRepositoryResponse);
assertThat(svnDiff)
.isEqualTo(getGitDiffWithoutIndexLine(gitDiff));
}
@Test
public void svnRenameChangesDiffShouldBeConvertedToGitDiff() throws IOException, URISyntaxException {
String fileName = "a.txt";
RepositoryUtil.createAndCommitFile(svnRepositoryClient, ADMIN_USERNAME, fileName, "content of a");
RepositoryUtil.createAndCommitFile(gitRepositoryClient, ADMIN_USERNAME, fileName, "content of a");
String newFileName = "renamed_a.txt";
File file = new File(svnRepositoryClient.getWorkingCopy(), fileName);
file.renameTo(new File(svnRepositoryClient.getWorkingCopy(), newFileName));
String svnDiff = getDiff(RepositoryUtil.addFileAndCommit(svnRepositoryClient, newFileName, ADMIN_USERNAME, "renamed file"), svnRepositoryResponse);
file = new File(gitRepositoryClient.getWorkingCopy(), fileName);
file.renameTo(new File(gitRepositoryClient.getWorkingCopy(), newFileName));
String gitDiff = getDiff(RepositoryUtil.addFileAndCommit(gitRepositoryClient, newFileName, ADMIN_USERNAME, "renamed file"), gitRepositoryResponse);
String expected = getGitDiffWithoutIndexLine(gitDiff);
assertThat(svnDiff)
.isEqualTo(expected);
}
public String getFileContent(String name) throws URISyntaxException, IOException {
Path path;
path = Paths.get(getClass().getResource(name).toURI());
Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();
return data;
}
/**
* The index line is not provided from the svn git formatter and it is not needed in the ui diff view
* for more details about the git diff format: https://git-scm.com/docs/git-diff
*
* @param gitDiff
* @return diff without the index line
*/
private String getGitDiffWithoutIndexLine(String gitDiff) {
return gitDiff.replaceAll(".*(index.*\n)", "");
}
private String getDiff(Changeset svnChangeset, ScmRequests.RepositoryResponse<ScmRequests.IndexResponse> svnRepositoryResponse) {
return svnRepositoryResponse.requestChangesets()
.requestDiffInGitFormat(svnChangeset.getId())
.getResponse()
.body()
.asString();
}
private Changeset applyMultipleChanges(RepositoryClient repositoryClient, String fileToBeDeleted, final String fileToBeUpdated, final String addedFile) throws IOException {
RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, fileToBeDeleted, "file to be deleted");
RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, fileToBeUpdated, "file to be updated");
Map<String, String> addedFiles = new HashMap<String, String>() {{
put(addedFile, "content");
}};
Map<String, String> modifiedFiles = new HashMap<String, String>() {{
put(fileToBeUpdated, "the updated content");
}};
ArrayList<String> removedFiles = Lists.newArrayList(fileToBeDeleted);
return RepositoryUtil.commitMultipleFileModifications(repositoryClient, ADMIN_USERNAME, addedFiles, modifiedFiles, removedFiles);
}
}

View File

@@ -1,5 +1,6 @@
package sonia.scm.it;
import groovy.util.logging.Slf4j;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import org.apache.http.HttpStatus;
@@ -37,6 +38,7 @@ import static sonia.scm.it.utils.RestUtil.given;
import static sonia.scm.it.utils.ScmTypes.availableScmTypes;
@RunWith(Parameterized.class)
@Slf4j
public class RepositoryAccessITCase {
@Rule
@@ -175,6 +177,7 @@ public class RepositoryAccessITCase {
}
@Test
@SuppressWarnings("squid:S2925")
public void shouldReadContent() throws IOException, InterruptedException {
RepositoryClient repositoryClient = RepositoryUtil.createRepositoryClient(repositoryType, folder);
RepositoryUtil.createAndCommitFile(repositoryClient, "scmadmin", "a.txt", "a");
@@ -262,40 +265,6 @@ 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")
@@ -393,12 +362,10 @@ public class RepositoryAccessITCase {
RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, "b.txt", "b");
RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, "c.txt", "c");
RepositoryUtil.createAndCommitFile(repositoryClient, ADMIN_USERNAME, "d.txt", "d");
Map<String, String> addedFiles = new HashMap<String, String>()
{{
Map<String, String> addedFiles = new HashMap<String, String>() {{
put("a.txt", "bla bla");
}};
Map<String, String> modifiedFiles = new HashMap<String, String>()
{{
Map<String, String> modifiedFiles = new HashMap<String, String>() {{
put("b.txt", "new content");
}};
ArrayList<String> removedFiles = Lists.newArrayList("c.txt", "d.txt");
@@ -414,7 +381,7 @@ public class RepositoryAccessITCase {
.assertAdded(a -> assertThat(a)
.hasSize(1)
.containsExactly("a.txt"))
.assertModified(m-> assertThat(m)
.assertModified(m -> assertThat(m)
.hasSize(1)
.containsExactly("b.txt"))
.assertRemoved(r -> assertThat(r)

View File

@@ -80,6 +80,11 @@ public class RepositoryUtil {
return file;
}
public static Changeset updateAndCommitFile(RepositoryClient repositoryClient, String username, String fileName, String content) throws IOException {
writeAndAddFile(repositoryClient, fileName, content);
return commit(repositoryClient, username, "updated " + fileName);
}
public static Changeset removeAndCommitFile(RepositoryClient repositoryClient, String username, String fileName) throws IOException {
deleteFileAndApplyRemoveCommand(repositoryClient, fileName);
return commit(repositoryClient, username, "removed " + fileName);
@@ -102,11 +107,21 @@ public class RepositoryUtil {
} else {
path = thisName;
}
repositoryClient.getAddCommand().add(path);
addFile(repositoryClient, path);
return path;
}
static Changeset commit(RepositoryClient repositoryClient, String username, String message) throws IOException {
public static Changeset addFileAndCommit(RepositoryClient repositoryClient, String path, String username, String message) throws IOException {
repositoryClient.getAddCommand().add(path);
return commit(repositoryClient, username, message);
}
public static void addFile(RepositoryClient repositoryClient, String path) throws IOException {
repositoryClient.getAddCommand().add(path);
}
public static Changeset commit(RepositoryClient repositoryClient, String username, String message) throws IOException {
LOG.info("user: {} try to commit with message: {}", username, message);
Changeset changeset = repositoryClient.getCommitCommand().commit(new Person(username, username + "@scm-manager.org"), message);
if (repositoryClient.isCommandSupported(ClientCommand.PUSH)) {

View File

@@ -234,8 +234,8 @@ public class ScmRequests {
return this;
}
public DiffResponse<ChangesetsResponse> requestDiff(String revision) {
return new DiffResponse<>(applyGETRequestFromLink(response, "_embedded.changesets.find{it.id=='" + revision + "'}._links.diff.href"), this);
public DiffResponse<ChangesetsResponse> requestDiffInGitFormat(String revision) {
return new DiffResponse<>(applyGETRequestFromLinkWithParams(response, "_embedded.changesets.find{it.id=='" + revision + "'}._links.diff.href", "?format=GIT"), this);
}
public ModificationsResponse<ChangesetsResponse> requestModifications(String revision) {
@@ -362,6 +362,10 @@ public class ScmRequests {
this.previousResponse = previousResponse;
}
public Response getResponse(){
return response;
}
public PREV returnToPrevious() {
return previousResponse;
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -113,27 +113,14 @@
<plugin>
<groupId>sonia.scm.maven</groupId>
<artifactId>smp-maven-plugin</artifactId>
<version>1.0.0-alpha-2</version>
<version>1.0.0-alpha-3</version>
<extensions>true</extensions>
<configuration>
<disableCompression>true</disableCompression>
<links>
<link>@scm-manager/ui-types</link>
<link>@scm-manager/ui-components</link>
</links>
</configuration>
<executions>
<execution>
<id>fix-descriptor</id>
<phase>process-resources</phase>
<goals>
<goal>fix-descriptor</goal>
</goals>
</execution>
<execution>
<id>append-dependencies</id>
<phase>process-classes</phase>
<goals>
<goal>append-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
@@ -148,57 +135,13 @@
<version>${yarn.version}</version>
</pkgManager>
<failOnMissingPackageJson>false</failOnMissingPackageJson>
<script>build</script>
</configuration>
<executions>
<execution>
<id>install</id>
<phase>process-resources</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
<execution>
<id>build</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>sonia.maven</groupId>
<artifactId>web-compressor</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compress-directory</goal>
</goals>
</execution>
</executions>
<configuration>
<replace>true</replace>
<baseDirectory>${project.build.directory}/classes</baseDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>doc</id>

View File

@@ -4,5 +4,6 @@
[include]
[libs]
./node_modules/@scm-manager/ui-components/flow-typed
[options]

View File

@@ -1,23 +0,0 @@
// flow-typed signature: cf86673cc32d185bdab1d2ea90578d37
// flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x
type $npm$classnames$Classes =
| string
| { [className: string]: * }
| false
| void
| null;
declare module "classnames" {
declare module.exports: (
...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]>
) => string;
}
declare module "classnames/bind" {
declare module.exports: $Exports<"classnames">;
}
declare module "classnames/dedupe" {
declare module.exports: $Exports<"classnames">;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,331 +0,0 @@
// flow-typed signature: 23b805356f90ad9384dd88489654e380
// flow-typed version: e9374c5fe9/moment_v2.3.x/flow_>=v0.25.x
type moment$MomentOptions = {
y?: number | string,
year?: number | string,
years?: number | string,
M?: number | string,
month?: number | string,
months?: number | string,
d?: number | string,
day?: number | string,
days?: number | string,
date?: number | string,
h?: number | string,
hour?: number | string,
hours?: number | string,
m?: number | string,
minute?: number | string,
minutes?: number | string,
s?: number | string,
second?: number | string,
seconds?: number | string,
ms?: number | string,
millisecond?: number | string,
milliseconds?: number | string
};
type moment$MomentObject = {
years: number,
months: number,
date: number,
hours: number,
minutes: number,
seconds: number,
milliseconds: number
};
type moment$MomentCreationData = {
input: string,
format: string,
locale: Object,
isUTC: boolean,
strict: boolean
};
type moment$CalendarFormat = string | ((moment: moment$Moment) => string);
type moment$CalendarFormats = {
sameDay?: moment$CalendarFormat,
nextDay?: moment$CalendarFormat,
nextWeek?: moment$CalendarFormat,
lastDay?: moment$CalendarFormat,
lastWeek?: moment$CalendarFormat,
sameElse?: moment$CalendarFormat
};
declare class moment$LocaleData {
months(moment: moment$Moment): string,
monthsShort(moment: moment$Moment): string,
monthsParse(month: string): number,
weekdays(moment: moment$Moment): string,
weekdaysShort(moment: moment$Moment): string,
weekdaysMin(moment: moment$Moment): string,
weekdaysParse(weekDay: string): number,
longDateFormat(dateFormat: string): string,
isPM(date: string): boolean,
meridiem(hours: number, minutes: number, isLower: boolean): string,
calendar(
key:
| "sameDay"
| "nextDay"
| "lastDay"
| "nextWeek"
| "prevWeek"
| "sameElse",
moment: moment$Moment
): string,
relativeTime(
number: number,
withoutSuffix: boolean,
key: "s" | "m" | "mm" | "h" | "hh" | "d" | "dd" | "M" | "MM" | "y" | "yy",
isFuture: boolean
): string,
pastFuture(diff: any, relTime: string): string,
ordinal(number: number): string,
preparse(str: string): any,
postformat(str: string): any,
week(moment: moment$Moment): string,
invalidDate(): string,
firstDayOfWeek(): number,
firstDayOfYear(): number
}
declare class moment$MomentDuration {
humanize(suffix?: boolean): string,
milliseconds(): number,
asMilliseconds(): number,
seconds(): number,
asSeconds(): number,
minutes(): number,
asMinutes(): number,
hours(): number,
asHours(): number,
days(): number,
asDays(): number,
months(): number,
asWeeks(): number,
weeks(): number,
asMonths(): number,
years(): number,
asYears(): number,
add(value: number | moment$MomentDuration | Object, unit?: string): this,
subtract(value: number | moment$MomentDuration | Object, unit?: string): this,
as(unit: string): number,
get(unit: string): number,
toJSON(): string,
toISOString(): string,
isValid(): boolean
}
declare class moment$Moment {
static ISO_8601: string,
static (
string?: string,
format?: string | Array<string>,
strict?: boolean
): moment$Moment,
static (
string?: string,
format?: string | Array<string>,
locale?: string,
strict?: boolean
): moment$Moment,
static (
initDate: ?Object | number | Date | Array<number> | moment$Moment | string
): moment$Moment,
static unix(seconds: number): moment$Moment,
static utc(): moment$Moment,
static utc(number: number | Array<number>): moment$Moment,
static utc(
str: string,
str2?: string | Array<string>,
str3?: string
): moment$Moment,
static utc(moment: moment$Moment): moment$Moment,
static utc(date: Date): moment$Moment,
static parseZone(): moment$Moment,
static parseZone(rawDate: string): moment$Moment,
static parseZone(
rawDate: string,
format: string | Array<string>
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
strict: boolean
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
locale: string,
strict: boolean
): moment$Moment,
isValid(): boolean,
invalidAt(): 0 | 1 | 2 | 3 | 4 | 5 | 6,
creationData(): moment$MomentCreationData,
millisecond(number: number): this,
milliseconds(number: number): this,
millisecond(): number,
milliseconds(): number,
second(number: number): this,
seconds(number: number): this,
second(): number,
seconds(): number,
minute(number: number): this,
minutes(number: number): this,
minute(): number,
minutes(): number,
hour(number: number): this,
hours(number: number): this,
hour(): number,
hours(): number,
date(number: number): this,
dates(number: number): this,
date(): number,
dates(): number,
day(day: number | string): this,
days(day: number | string): this,
day(): number,
days(): number,
weekday(number: number): this,
weekday(): number,
isoWeekday(number: number): this,
isoWeekday(): number,
dayOfYear(number: number): this,
dayOfYear(): number,
week(number: number): this,
weeks(number: number): this,
week(): number,
weeks(): number,
isoWeek(number: number): this,
isoWeeks(number: number): this,
isoWeek(): number,
isoWeeks(): number,
month(number: number): this,
months(number: number): this,
month(): number,
months(): number,
quarter(number: number): this,
quarter(): number,
year(number: number): this,
years(number: number): this,
year(): number,
years(): number,
weekYear(number: number): this,
weekYear(): number,
isoWeekYear(number: number): this,
isoWeekYear(): number,
weeksInYear(): number,
isoWeeksInYear(): number,
get(string: string): number,
set(unit: string, value: number): this,
set(options: { [unit: string]: number }): this,
static max(...dates: Array<moment$Moment>): moment$Moment,
static max(dates: Array<moment$Moment>): moment$Moment,
static min(...dates: Array<moment$Moment>): moment$Moment,
static min(dates: Array<moment$Moment>): moment$Moment,
add(
value: number | moment$MomentDuration | moment$Moment | Object,
unit?: string
): this,
subtract(
value: number | moment$MomentDuration | moment$Moment | string | Object,
unit?: string
): this,
startOf(unit: string): this,
endOf(unit: string): this,
local(): this,
utc(): this,
utcOffset(
offset: number | string,
keepLocalTime?: boolean,
keepMinutes?: boolean
): this,
utcOffset(): number,
format(format?: string): string,
fromNow(removeSuffix?: boolean): string,
from(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
toNow(removePrefix?: boolean): string,
to(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
calendar(refTime?: any, formats?: moment$CalendarFormats): string,
diff(
date: moment$Moment | string | number | Date | Array<number>,
format?: string,
floating?: boolean
): number,
valueOf(): number,
unix(): number,
daysInMonth(): number,
toDate(): Date,
toArray(): Array<number>,
toJSON(): string,
toISOString(
keepOffset?: boolean
): string,
toObject(): moment$MomentObject,
isBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSame(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isBetween(
fromDate: moment$Moment | string | number | Date | Array<number>,
toDate?: ?moment$Moment | string | number | Date | Array<number>,
granularity?: ?string,
inclusion?: ?string
): boolean,
isDST(): boolean,
isDSTShifted(): boolean,
isLeapYear(): boolean,
clone(): moment$Moment,
static isMoment(obj: any): boolean,
static isDate(obj: any): boolean,
static locale(locale: string, localeData?: Object): string,
static updateLocale(locale: string, localeData?: ?Object): void,
static locale(locales: Array<string>): string,
locale(locale: string, customization?: Object | null): moment$Moment,
locale(): string,
static months(): Array<string>,
static monthsShort(): Array<string>,
static weekdays(): Array<string>,
static weekdaysShort(): Array<string>,
static weekdaysMin(): Array<string>,
static months(): string,
static monthsShort(): string,
static weekdays(): string,
static weekdaysShort(): string,
static weekdaysMin(): string,
static localeData(key?: string): moment$LocaleData,
static duration(
value: number | Object | string,
unit?: string
): moment$MomentDuration,
static isDuration(obj: any): boolean,
static normalizeUnits(unit: string): string,
static invalid(object: any): moment$Moment
}
declare module "moment" {
declare module.exports: Class<moment$Moment>;
}

View File

@@ -1,137 +0,0 @@
// flow-typed signature: ba35d02d668b0d0a3e04a63a6847974e
// flow-typed version: <<STUB>>/react-jss_v8.6.1/flow_v0.79.1
/**
* This is an autogenerated libdef stub for:
*
* 'react-jss'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'react-jss' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'react-jss/dist/react-jss' {
declare module.exports: any;
}
declare module 'react-jss/dist/react-jss.min' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/contextTypes' {
declare module.exports: any;
}
declare module 'react-jss/lib/createHoc' {
declare module.exports: any;
}
declare module 'react-jss/lib/getDisplayName' {
declare module.exports: any;
}
declare module 'react-jss/lib/index' {
declare module.exports: any;
}
declare module 'react-jss/lib/index.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/jss' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/ns' {
declare module.exports: any;
}
declare module 'react-jss/lib/propTypes' {
declare module.exports: any;
}
// Filename aliases
declare module 'react-jss/dist/react-jss.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss'>;
}
declare module 'react-jss/dist/react-jss.min.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss.min'>;
}
declare module 'react-jss/lib/compose.js' {
declare module.exports: $Exports<'react-jss/lib/compose'>;
}
declare module 'react-jss/lib/compose.test.js' {
declare module.exports: $Exports<'react-jss/lib/compose.test'>;
}
declare module 'react-jss/lib/contextTypes.js' {
declare module.exports: $Exports<'react-jss/lib/contextTypes'>;
}
declare module 'react-jss/lib/createHoc.js' {
declare module.exports: $Exports<'react-jss/lib/createHoc'>;
}
declare module 'react-jss/lib/getDisplayName.js' {
declare module.exports: $Exports<'react-jss/lib/getDisplayName'>;
}
declare module 'react-jss/lib/index.js' {
declare module.exports: $Exports<'react-jss/lib/index'>;
}
declare module 'react-jss/lib/index.test.js' {
declare module.exports: $Exports<'react-jss/lib/index.test'>;
}
declare module 'react-jss/lib/injectSheet.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet'>;
}
declare module 'react-jss/lib/injectSheet.test.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet.test'>;
}
declare module 'react-jss/lib/jss.js' {
declare module.exports: $Exports<'react-jss/lib/jss'>;
}
declare module 'react-jss/lib/JssProvider.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider'>;
}
declare module 'react-jss/lib/JssProvider.test.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider.test'>;
}
declare module 'react-jss/lib/ns.js' {
declare module.exports: $Exports<'react-jss/lib/ns'>;
}
declare module 'react-jss/lib/propTypes.js' {
declare module.exports: $Exports<'react-jss/lib/propTypes'>;
}

View File

@@ -3,12 +3,15 @@
"license" : "BSD-3-Clause",
"main": "src/main/js/index.js",
"scripts": {
"build": "ui-bundler plugin"
"build": "ui-bundler plugin",
"watch": "ui-bundler plugin -w",
"lint": "ui-bundler lint",
"flow": "flow check"
},
"dependencies": {
"@scm-manager/ui-extensions": "^0.0.7"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17"
"@scm-manager/ui-bundler": "^0.0.19"
}
}

View File

@@ -43,11 +43,20 @@
</dependencies>
<!-- create test jar -->
<build>
<plugins>
<plugin>
<groupId>sonia.scm.maven</groupId>
<artifactId>smp-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<corePlugin>true</corePlugin>
</configuration>
</plugin>
<!-- create test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -61,33 +70,6 @@
</executions>
</plugin>
<plugin>
<groupId>com.github.sdorra</groupId>
<artifactId>buildfrontend-maven-plugin</artifactId>
<executions>
<execution>
<id>link-ui-types</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-types</pkg>
</configuration>
</execution>
<execution>
<id>link-ui-components</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-components</pkg>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -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.17":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.17.tgz#949b90ca57e4268be28fcf4975bd9622f60278bb"
"@scm-manager/ui-bundler@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.19.tgz#646ab1fa1e5389fad614542215c60678fb9816ae"
dependencies:
"@babel/core" "^7.0.0"
"@babel/plugin-proposal-class-properties" "^7.0.0"

View File

@@ -4,5 +4,6 @@
[include]
[libs]
./node_modules/@scm-manager/ui-components/flow-typed
[options]

View File

@@ -1,23 +0,0 @@
// flow-typed signature: cf86673cc32d185bdab1d2ea90578d37
// flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x
type $npm$classnames$Classes =
| string
| { [className: string]: * }
| false
| void
| null;
declare module "classnames" {
declare module.exports: (
...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]>
) => string;
}
declare module "classnames/bind" {
declare module.exports: $Exports<"classnames">;
}
declare module "classnames/dedupe" {
declare module.exports: $Exports<"classnames">;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,331 +0,0 @@
// flow-typed signature: 23b805356f90ad9384dd88489654e380
// flow-typed version: e9374c5fe9/moment_v2.3.x/flow_>=v0.25.x
type moment$MomentOptions = {
y?: number | string,
year?: number | string,
years?: number | string,
M?: number | string,
month?: number | string,
months?: number | string,
d?: number | string,
day?: number | string,
days?: number | string,
date?: number | string,
h?: number | string,
hour?: number | string,
hours?: number | string,
m?: number | string,
minute?: number | string,
minutes?: number | string,
s?: number | string,
second?: number | string,
seconds?: number | string,
ms?: number | string,
millisecond?: number | string,
milliseconds?: number | string
};
type moment$MomentObject = {
years: number,
months: number,
date: number,
hours: number,
minutes: number,
seconds: number,
milliseconds: number
};
type moment$MomentCreationData = {
input: string,
format: string,
locale: Object,
isUTC: boolean,
strict: boolean
};
type moment$CalendarFormat = string | ((moment: moment$Moment) => string);
type moment$CalendarFormats = {
sameDay?: moment$CalendarFormat,
nextDay?: moment$CalendarFormat,
nextWeek?: moment$CalendarFormat,
lastDay?: moment$CalendarFormat,
lastWeek?: moment$CalendarFormat,
sameElse?: moment$CalendarFormat
};
declare class moment$LocaleData {
months(moment: moment$Moment): string,
monthsShort(moment: moment$Moment): string,
monthsParse(month: string): number,
weekdays(moment: moment$Moment): string,
weekdaysShort(moment: moment$Moment): string,
weekdaysMin(moment: moment$Moment): string,
weekdaysParse(weekDay: string): number,
longDateFormat(dateFormat: string): string,
isPM(date: string): boolean,
meridiem(hours: number, minutes: number, isLower: boolean): string,
calendar(
key:
| "sameDay"
| "nextDay"
| "lastDay"
| "nextWeek"
| "prevWeek"
| "sameElse",
moment: moment$Moment
): string,
relativeTime(
number: number,
withoutSuffix: boolean,
key: "s" | "m" | "mm" | "h" | "hh" | "d" | "dd" | "M" | "MM" | "y" | "yy",
isFuture: boolean
): string,
pastFuture(diff: any, relTime: string): string,
ordinal(number: number): string,
preparse(str: string): any,
postformat(str: string): any,
week(moment: moment$Moment): string,
invalidDate(): string,
firstDayOfWeek(): number,
firstDayOfYear(): number
}
declare class moment$MomentDuration {
humanize(suffix?: boolean): string,
milliseconds(): number,
asMilliseconds(): number,
seconds(): number,
asSeconds(): number,
minutes(): number,
asMinutes(): number,
hours(): number,
asHours(): number,
days(): number,
asDays(): number,
months(): number,
asWeeks(): number,
weeks(): number,
asMonths(): number,
years(): number,
asYears(): number,
add(value: number | moment$MomentDuration | Object, unit?: string): this,
subtract(value: number | moment$MomentDuration | Object, unit?: string): this,
as(unit: string): number,
get(unit: string): number,
toJSON(): string,
toISOString(): string,
isValid(): boolean
}
declare class moment$Moment {
static ISO_8601: string,
static (
string?: string,
format?: string | Array<string>,
strict?: boolean
): moment$Moment,
static (
string?: string,
format?: string | Array<string>,
locale?: string,
strict?: boolean
): moment$Moment,
static (
initDate: ?Object | number | Date | Array<number> | moment$Moment | string
): moment$Moment,
static unix(seconds: number): moment$Moment,
static utc(): moment$Moment,
static utc(number: number | Array<number>): moment$Moment,
static utc(
str: string,
str2?: string | Array<string>,
str3?: string
): moment$Moment,
static utc(moment: moment$Moment): moment$Moment,
static utc(date: Date): moment$Moment,
static parseZone(): moment$Moment,
static parseZone(rawDate: string): moment$Moment,
static parseZone(
rawDate: string,
format: string | Array<string>
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
strict: boolean
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
locale: string,
strict: boolean
): moment$Moment,
isValid(): boolean,
invalidAt(): 0 | 1 | 2 | 3 | 4 | 5 | 6,
creationData(): moment$MomentCreationData,
millisecond(number: number): this,
milliseconds(number: number): this,
millisecond(): number,
milliseconds(): number,
second(number: number): this,
seconds(number: number): this,
second(): number,
seconds(): number,
minute(number: number): this,
minutes(number: number): this,
minute(): number,
minutes(): number,
hour(number: number): this,
hours(number: number): this,
hour(): number,
hours(): number,
date(number: number): this,
dates(number: number): this,
date(): number,
dates(): number,
day(day: number | string): this,
days(day: number | string): this,
day(): number,
days(): number,
weekday(number: number): this,
weekday(): number,
isoWeekday(number: number): this,
isoWeekday(): number,
dayOfYear(number: number): this,
dayOfYear(): number,
week(number: number): this,
weeks(number: number): this,
week(): number,
weeks(): number,
isoWeek(number: number): this,
isoWeeks(number: number): this,
isoWeek(): number,
isoWeeks(): number,
month(number: number): this,
months(number: number): this,
month(): number,
months(): number,
quarter(number: number): this,
quarter(): number,
year(number: number): this,
years(number: number): this,
year(): number,
years(): number,
weekYear(number: number): this,
weekYear(): number,
isoWeekYear(number: number): this,
isoWeekYear(): number,
weeksInYear(): number,
isoWeeksInYear(): number,
get(string: string): number,
set(unit: string, value: number): this,
set(options: { [unit: string]: number }): this,
static max(...dates: Array<moment$Moment>): moment$Moment,
static max(dates: Array<moment$Moment>): moment$Moment,
static min(...dates: Array<moment$Moment>): moment$Moment,
static min(dates: Array<moment$Moment>): moment$Moment,
add(
value: number | moment$MomentDuration | moment$Moment | Object,
unit?: string
): this,
subtract(
value: number | moment$MomentDuration | moment$Moment | string | Object,
unit?: string
): this,
startOf(unit: string): this,
endOf(unit: string): this,
local(): this,
utc(): this,
utcOffset(
offset: number | string,
keepLocalTime?: boolean,
keepMinutes?: boolean
): this,
utcOffset(): number,
format(format?: string): string,
fromNow(removeSuffix?: boolean): string,
from(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
toNow(removePrefix?: boolean): string,
to(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
calendar(refTime?: any, formats?: moment$CalendarFormats): string,
diff(
date: moment$Moment | string | number | Date | Array<number>,
format?: string,
floating?: boolean
): number,
valueOf(): number,
unix(): number,
daysInMonth(): number,
toDate(): Date,
toArray(): Array<number>,
toJSON(): string,
toISOString(
keepOffset?: boolean
): string,
toObject(): moment$MomentObject,
isBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSame(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isBetween(
fromDate: moment$Moment | string | number | Date | Array<number>,
toDate?: ?moment$Moment | string | number | Date | Array<number>,
granularity?: ?string,
inclusion?: ?string
): boolean,
isDST(): boolean,
isDSTShifted(): boolean,
isLeapYear(): boolean,
clone(): moment$Moment,
static isMoment(obj: any): boolean,
static isDate(obj: any): boolean,
static locale(locale: string, localeData?: Object): string,
static updateLocale(locale: string, localeData?: ?Object): void,
static locale(locales: Array<string>): string,
locale(locale: string, customization?: Object | null): moment$Moment,
locale(): string,
static months(): Array<string>,
static monthsShort(): Array<string>,
static weekdays(): Array<string>,
static weekdaysShort(): Array<string>,
static weekdaysMin(): Array<string>,
static months(): string,
static monthsShort(): string,
static weekdays(): string,
static weekdaysShort(): string,
static weekdaysMin(): string,
static localeData(key?: string): moment$LocaleData,
static duration(
value: number | Object | string,
unit?: string
): moment$MomentDuration,
static isDuration(obj: any): boolean,
static normalizeUnits(unit: string): string,
static invalid(object: any): moment$Moment
}
declare module "moment" {
declare module.exports: Class<moment$Moment>;
}

View File

@@ -1,137 +0,0 @@
// flow-typed signature: ba35d02d668b0d0a3e04a63a6847974e
// flow-typed version: <<STUB>>/react-jss_v8.6.1/flow_v0.79.1
/**
* This is an autogenerated libdef stub for:
*
* 'react-jss'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'react-jss' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'react-jss/dist/react-jss' {
declare module.exports: any;
}
declare module 'react-jss/dist/react-jss.min' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/contextTypes' {
declare module.exports: any;
}
declare module 'react-jss/lib/createHoc' {
declare module.exports: any;
}
declare module 'react-jss/lib/getDisplayName' {
declare module.exports: any;
}
declare module 'react-jss/lib/index' {
declare module.exports: any;
}
declare module 'react-jss/lib/index.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/jss' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/ns' {
declare module.exports: any;
}
declare module 'react-jss/lib/propTypes' {
declare module.exports: any;
}
// Filename aliases
declare module 'react-jss/dist/react-jss.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss'>;
}
declare module 'react-jss/dist/react-jss.min.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss.min'>;
}
declare module 'react-jss/lib/compose.js' {
declare module.exports: $Exports<'react-jss/lib/compose'>;
}
declare module 'react-jss/lib/compose.test.js' {
declare module.exports: $Exports<'react-jss/lib/compose.test'>;
}
declare module 'react-jss/lib/contextTypes.js' {
declare module.exports: $Exports<'react-jss/lib/contextTypes'>;
}
declare module 'react-jss/lib/createHoc.js' {
declare module.exports: $Exports<'react-jss/lib/createHoc'>;
}
declare module 'react-jss/lib/getDisplayName.js' {
declare module.exports: $Exports<'react-jss/lib/getDisplayName'>;
}
declare module 'react-jss/lib/index.js' {
declare module.exports: $Exports<'react-jss/lib/index'>;
}
declare module 'react-jss/lib/index.test.js' {
declare module.exports: $Exports<'react-jss/lib/index.test'>;
}
declare module 'react-jss/lib/injectSheet.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet'>;
}
declare module 'react-jss/lib/injectSheet.test.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet.test'>;
}
declare module 'react-jss/lib/jss.js' {
declare module.exports: $Exports<'react-jss/lib/jss'>;
}
declare module 'react-jss/lib/JssProvider.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider'>;
}
declare module 'react-jss/lib/JssProvider.test.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider.test'>;
}
declare module 'react-jss/lib/ns.js' {
declare module.exports: $Exports<'react-jss/lib/ns'>;
}
declare module 'react-jss/lib/propTypes.js' {
declare module.exports: $Exports<'react-jss/lib/propTypes'>;
}

View File

@@ -9,6 +9,6 @@
"@scm-manager/ui-extensions": "^0.0.7"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17"
"@scm-manager/ui-bundler": "^0.0.19"
}
}

View File

@@ -31,8 +31,6 @@
</dependencies>
<!-- create test jar -->
<build>
<plugins>
@@ -55,6 +53,17 @@
</configuration>
</plugin>
<plugin>
<groupId>sonia.scm.maven</groupId>
<artifactId>smp-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<corePlugin>true</corePlugin>
</configuration>
</plugin>
<!-- create test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -68,33 +77,6 @@
</executions>
</plugin>
<plugin>
<groupId>com.github.sdorra</groupId>
<artifactId>buildfrontend-maven-plugin</artifactId>
<executions>
<execution>
<id>link-ui-types</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-types</pkg>
</configuration>
</execution>
<execution>
<id>link-ui-components</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-components</pkg>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -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.17":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.17.tgz#949b90ca57e4268be28fcf4975bd9622f60278bb"
"@scm-manager/ui-bundler@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.19.tgz#646ab1fa1e5389fad614542215c60678fb9816ae"
dependencies:
"@babel/core" "^7.0.0"
"@babel/plugin-proposal-class-properties" "^7.0.0"
@@ -660,6 +660,7 @@
browserify-css "^0.14.0"
colors "^1.3.1"
commander "^2.17.1"
connect-history-api-fallback "^1.5.0"
eslint "^5.4.0"
eslint-config-react-app "^2.1.0"
eslint-plugin-flowtype "^2.50.0"

View File

@@ -23,4 +23,19 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>sonia.scm.maven</groupId>
<artifactId>smp-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<corePlugin>true</corePlugin>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -4,5 +4,6 @@
[include]
[libs]
./node_modules/@scm-manager/ui-components/flow-typed
[options]

View File

@@ -1,23 +0,0 @@
// flow-typed signature: cf86673cc32d185bdab1d2ea90578d37
// flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x
type $npm$classnames$Classes =
| string
| { [className: string]: * }
| false
| void
| null;
declare module "classnames" {
declare module.exports: (
...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]>
) => string;
}
declare module "classnames/bind" {
declare module.exports: $Exports<"classnames">;
}
declare module "classnames/dedupe" {
declare module.exports: $Exports<"classnames">;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,331 +0,0 @@
// flow-typed signature: 23b805356f90ad9384dd88489654e380
// flow-typed version: e9374c5fe9/moment_v2.3.x/flow_>=v0.25.x
type moment$MomentOptions = {
y?: number | string,
year?: number | string,
years?: number | string,
M?: number | string,
month?: number | string,
months?: number | string,
d?: number | string,
day?: number | string,
days?: number | string,
date?: number | string,
h?: number | string,
hour?: number | string,
hours?: number | string,
m?: number | string,
minute?: number | string,
minutes?: number | string,
s?: number | string,
second?: number | string,
seconds?: number | string,
ms?: number | string,
millisecond?: number | string,
milliseconds?: number | string
};
type moment$MomentObject = {
years: number,
months: number,
date: number,
hours: number,
minutes: number,
seconds: number,
milliseconds: number
};
type moment$MomentCreationData = {
input: string,
format: string,
locale: Object,
isUTC: boolean,
strict: boolean
};
type moment$CalendarFormat = string | ((moment: moment$Moment) => string);
type moment$CalendarFormats = {
sameDay?: moment$CalendarFormat,
nextDay?: moment$CalendarFormat,
nextWeek?: moment$CalendarFormat,
lastDay?: moment$CalendarFormat,
lastWeek?: moment$CalendarFormat,
sameElse?: moment$CalendarFormat
};
declare class moment$LocaleData {
months(moment: moment$Moment): string,
monthsShort(moment: moment$Moment): string,
monthsParse(month: string): number,
weekdays(moment: moment$Moment): string,
weekdaysShort(moment: moment$Moment): string,
weekdaysMin(moment: moment$Moment): string,
weekdaysParse(weekDay: string): number,
longDateFormat(dateFormat: string): string,
isPM(date: string): boolean,
meridiem(hours: number, minutes: number, isLower: boolean): string,
calendar(
key:
| "sameDay"
| "nextDay"
| "lastDay"
| "nextWeek"
| "prevWeek"
| "sameElse",
moment: moment$Moment
): string,
relativeTime(
number: number,
withoutSuffix: boolean,
key: "s" | "m" | "mm" | "h" | "hh" | "d" | "dd" | "M" | "MM" | "y" | "yy",
isFuture: boolean
): string,
pastFuture(diff: any, relTime: string): string,
ordinal(number: number): string,
preparse(str: string): any,
postformat(str: string): any,
week(moment: moment$Moment): string,
invalidDate(): string,
firstDayOfWeek(): number,
firstDayOfYear(): number
}
declare class moment$MomentDuration {
humanize(suffix?: boolean): string,
milliseconds(): number,
asMilliseconds(): number,
seconds(): number,
asSeconds(): number,
minutes(): number,
asMinutes(): number,
hours(): number,
asHours(): number,
days(): number,
asDays(): number,
months(): number,
asWeeks(): number,
weeks(): number,
asMonths(): number,
years(): number,
asYears(): number,
add(value: number | moment$MomentDuration | Object, unit?: string): this,
subtract(value: number | moment$MomentDuration | Object, unit?: string): this,
as(unit: string): number,
get(unit: string): number,
toJSON(): string,
toISOString(): string,
isValid(): boolean
}
declare class moment$Moment {
static ISO_8601: string,
static (
string?: string,
format?: string | Array<string>,
strict?: boolean
): moment$Moment,
static (
string?: string,
format?: string | Array<string>,
locale?: string,
strict?: boolean
): moment$Moment,
static (
initDate: ?Object | number | Date | Array<number> | moment$Moment | string
): moment$Moment,
static unix(seconds: number): moment$Moment,
static utc(): moment$Moment,
static utc(number: number | Array<number>): moment$Moment,
static utc(
str: string,
str2?: string | Array<string>,
str3?: string
): moment$Moment,
static utc(moment: moment$Moment): moment$Moment,
static utc(date: Date): moment$Moment,
static parseZone(): moment$Moment,
static parseZone(rawDate: string): moment$Moment,
static parseZone(
rawDate: string,
format: string | Array<string>
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
strict: boolean
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
locale: string,
strict: boolean
): moment$Moment,
isValid(): boolean,
invalidAt(): 0 | 1 | 2 | 3 | 4 | 5 | 6,
creationData(): moment$MomentCreationData,
millisecond(number: number): this,
milliseconds(number: number): this,
millisecond(): number,
milliseconds(): number,
second(number: number): this,
seconds(number: number): this,
second(): number,
seconds(): number,
minute(number: number): this,
minutes(number: number): this,
minute(): number,
minutes(): number,
hour(number: number): this,
hours(number: number): this,
hour(): number,
hours(): number,
date(number: number): this,
dates(number: number): this,
date(): number,
dates(): number,
day(day: number | string): this,
days(day: number | string): this,
day(): number,
days(): number,
weekday(number: number): this,
weekday(): number,
isoWeekday(number: number): this,
isoWeekday(): number,
dayOfYear(number: number): this,
dayOfYear(): number,
week(number: number): this,
weeks(number: number): this,
week(): number,
weeks(): number,
isoWeek(number: number): this,
isoWeeks(number: number): this,
isoWeek(): number,
isoWeeks(): number,
month(number: number): this,
months(number: number): this,
month(): number,
months(): number,
quarter(number: number): this,
quarter(): number,
year(number: number): this,
years(number: number): this,
year(): number,
years(): number,
weekYear(number: number): this,
weekYear(): number,
isoWeekYear(number: number): this,
isoWeekYear(): number,
weeksInYear(): number,
isoWeeksInYear(): number,
get(string: string): number,
set(unit: string, value: number): this,
set(options: { [unit: string]: number }): this,
static max(...dates: Array<moment$Moment>): moment$Moment,
static max(dates: Array<moment$Moment>): moment$Moment,
static min(...dates: Array<moment$Moment>): moment$Moment,
static min(dates: Array<moment$Moment>): moment$Moment,
add(
value: number | moment$MomentDuration | moment$Moment | Object,
unit?: string
): this,
subtract(
value: number | moment$MomentDuration | moment$Moment | string | Object,
unit?: string
): this,
startOf(unit: string): this,
endOf(unit: string): this,
local(): this,
utc(): this,
utcOffset(
offset: number | string,
keepLocalTime?: boolean,
keepMinutes?: boolean
): this,
utcOffset(): number,
format(format?: string): string,
fromNow(removeSuffix?: boolean): string,
from(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
toNow(removePrefix?: boolean): string,
to(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
calendar(refTime?: any, formats?: moment$CalendarFormats): string,
diff(
date: moment$Moment | string | number | Date | Array<number>,
format?: string,
floating?: boolean
): number,
valueOf(): number,
unix(): number,
daysInMonth(): number,
toDate(): Date,
toArray(): Array<number>,
toJSON(): string,
toISOString(
keepOffset?: boolean
): string,
toObject(): moment$MomentObject,
isBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSame(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isBetween(
fromDate: moment$Moment | string | number | Date | Array<number>,
toDate?: ?moment$Moment | string | number | Date | Array<number>,
granularity?: ?string,
inclusion?: ?string
): boolean,
isDST(): boolean,
isDSTShifted(): boolean,
isLeapYear(): boolean,
clone(): moment$Moment,
static isMoment(obj: any): boolean,
static isDate(obj: any): boolean,
static locale(locale: string, localeData?: Object): string,
static updateLocale(locale: string, localeData?: ?Object): void,
static locale(locales: Array<string>): string,
locale(locale: string, customization?: Object | null): moment$Moment,
locale(): string,
static months(): Array<string>,
static monthsShort(): Array<string>,
static weekdays(): Array<string>,
static weekdaysShort(): Array<string>,
static weekdaysMin(): Array<string>,
static months(): string,
static monthsShort(): string,
static weekdays(): string,
static weekdaysShort(): string,
static weekdaysMin(): string,
static localeData(key?: string): moment$LocaleData,
static duration(
value: number | Object | string,
unit?: string
): moment$MomentDuration,
static isDuration(obj: any): boolean,
static normalizeUnits(unit: string): string,
static invalid(object: any): moment$Moment
}
declare module "moment" {
declare module.exports: Class<moment$Moment>;
}

View File

@@ -1,137 +0,0 @@
// flow-typed signature: ba35d02d668b0d0a3e04a63a6847974e
// flow-typed version: <<STUB>>/react-jss_v8.6.1/flow_v0.79.1
/**
* This is an autogenerated libdef stub for:
*
* 'react-jss'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'react-jss' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'react-jss/dist/react-jss' {
declare module.exports: any;
}
declare module 'react-jss/dist/react-jss.min' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose' {
declare module.exports: any;
}
declare module 'react-jss/lib/compose.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/contextTypes' {
declare module.exports: any;
}
declare module 'react-jss/lib/createHoc' {
declare module.exports: any;
}
declare module 'react-jss/lib/getDisplayName' {
declare module.exports: any;
}
declare module 'react-jss/lib/index' {
declare module.exports: any;
}
declare module 'react-jss/lib/index.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet' {
declare module.exports: any;
}
declare module 'react-jss/lib/injectSheet.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/jss' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider' {
declare module.exports: any;
}
declare module 'react-jss/lib/JssProvider.test' {
declare module.exports: any;
}
declare module 'react-jss/lib/ns' {
declare module.exports: any;
}
declare module 'react-jss/lib/propTypes' {
declare module.exports: any;
}
// Filename aliases
declare module 'react-jss/dist/react-jss.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss'>;
}
declare module 'react-jss/dist/react-jss.min.js' {
declare module.exports: $Exports<'react-jss/dist/react-jss.min'>;
}
declare module 'react-jss/lib/compose.js' {
declare module.exports: $Exports<'react-jss/lib/compose'>;
}
declare module 'react-jss/lib/compose.test.js' {
declare module.exports: $Exports<'react-jss/lib/compose.test'>;
}
declare module 'react-jss/lib/contextTypes.js' {
declare module.exports: $Exports<'react-jss/lib/contextTypes'>;
}
declare module 'react-jss/lib/createHoc.js' {
declare module.exports: $Exports<'react-jss/lib/createHoc'>;
}
declare module 'react-jss/lib/getDisplayName.js' {
declare module.exports: $Exports<'react-jss/lib/getDisplayName'>;
}
declare module 'react-jss/lib/index.js' {
declare module.exports: $Exports<'react-jss/lib/index'>;
}
declare module 'react-jss/lib/index.test.js' {
declare module.exports: $Exports<'react-jss/lib/index.test'>;
}
declare module 'react-jss/lib/injectSheet.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet'>;
}
declare module 'react-jss/lib/injectSheet.test.js' {
declare module.exports: $Exports<'react-jss/lib/injectSheet.test'>;
}
declare module 'react-jss/lib/jss.js' {
declare module.exports: $Exports<'react-jss/lib/jss'>;
}
declare module 'react-jss/lib/JssProvider.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider'>;
}
declare module 'react-jss/lib/JssProvider.test.js' {
declare module.exports: $Exports<'react-jss/lib/JssProvider.test'>;
}
declare module 'react-jss/lib/ns.js' {
declare module.exports: $Exports<'react-jss/lib/ns'>;
}
declare module 'react-jss/lib/propTypes.js' {
declare module.exports: $Exports<'react-jss/lib/propTypes'>;
}

View File

@@ -9,6 +9,6 @@
"@scm-manager/ui-extensions": "^0.0.7"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17"
"@scm-manager/ui-bundler": "^0.0.19"
}
}

View File

@@ -37,11 +37,19 @@
</dependencies>
<!-- create test jar -->
<build>
<plugins>
<plugin>
<groupId>sonia.scm.maven</groupId>
<artifactId>smp-maven-plugin</artifactId>
<configuration>
<corePlugin>true</corePlugin>
</configuration>
</plugin>
<!-- create test jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -55,34 +63,6 @@
</executions>
</plugin>
<plugin>
<groupId>com.github.sdorra</groupId>
<artifactId>buildfrontend-maven-plugin</artifactId>
<executions>
<execution>
<id>link-ui-types</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-types</pkg>
</configuration>
</execution>
<execution>
<id>link-ui-components</id>
<phase>process-sources</phase>
<goals>
<goal>install-link</goal>
</goals>
<configuration>
<pkg>@scm-manager/ui-components</pkg>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -1,10 +1,10 @@
/**
/*
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* <p>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* <p>
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
@@ -13,7 +13,7 @@
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,13 +24,11 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* <p>
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
@@ -41,8 +39,7 @@ import org.slf4j.LoggerFactory;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.DefaultSVNDiffGenerator;
import org.tmatesoft.svn.core.wc.ISVNDiffGenerator;
import org.tmatesoft.svn.core.internal.wc2.ng.SvnNewDiffGenerator;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNDiffClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -60,8 +57,7 @@ import java.io.OutputStream;
*
* @author Sebastian Sdorra
*/
public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand
{
public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand {
/**
* the logger for SvnDiffCommand
@@ -69,46 +65,26 @@ public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand
private static final Logger logger =
LoggerFactory.getLogger(SvnDiffCommand.class);
public SvnDiffCommand(SvnContext context, Repository repository)
{
public SvnDiffCommand(SvnContext context, Repository repository) {
super(context, repository);
}
@Override
public void getDiffResult(DiffCommandRequest request, OutputStream output) {
if (logger.isDebugEnabled())
{
logger.debug("create diff for {}", request);
}
Preconditions.checkNotNull(request, "request is required");
Preconditions.checkNotNull(output, "outputstream is required");
String path = request.getPath();
SVNClientManager clientManager = null;
try
{
try {
SVNURL svnurl = context.createUrl();
if (Util.isNotEmpty(path))
{
if (Util.isNotEmpty(path)) {
svnurl = svnurl.appendPath(path, true);
}
clientManager = SVNClientManager.newInstance();
SVNDiffClient diffClient = clientManager.getDiffClient();
ISVNDiffGenerator diffGenerator = diffClient.getDiffGenerator();
if (diffGenerator == null)
{
diffGenerator = new DefaultSVNDiffGenerator();
}
diffGenerator.setDiffAdded(true);
diffGenerator.setDiffDeleted(true);
diffClient.setDiffGenerator(diffGenerator);
diffClient.setDiffGenerator(new SvnNewDiffGenerator(new SCMSvnDiffGenerator()));
long currentRev = SvnUtil.getRevisionNumber(request.getRevision(), repository);
@@ -117,13 +93,9 @@ public class SvnDiffCommand extends AbstractSvnCommand implements DiffCommand
diffClient.doDiff(svnurl, SVNRevision.HEAD,
SVNRevision.create(currentRev - 1), SVNRevision.create(currentRev),
SVNDepth.INFINITY, false, output);
}
catch (SVNException ex)
{
} catch (SVNException ex) {
throw new InternalRepositoryException(repository, "could not create diff", ex);
}
finally
{
} finally {
SvnUtil.dispose(clientManager);
}
}

View File

@@ -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.17":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.17.tgz#949b90ca57e4268be28fcf4975bd9622f60278bb"
"@scm-manager/ui-bundler@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.19.tgz#646ab1fa1e5389fad614542215c60678fb9816ae"
dependencies:
"@babel/core" "^7.0.0"
"@babel/plugin-proposal-class-properties" "^7.0.0"

View File

@@ -0,0 +1,95 @@
// flow-typed signature: 65d42f62f8de603dcc631ea5a6b00580
// flow-typed version: f3f13164e0/react-i18next_v7.x.x/flow_>=v0.64.x
declare module "react-i18next" {
declare type TFunction = (key?: ?string, data?: ?Object) => string;
declare type TranslatorProps = {|
t: TFunction,
i18nLoadedAt: Date,
i18n: Object
|};
declare type TranslatorPropsVoid = {
t: TFunction | void,
i18nLoadedAt: Date | void,
i18n: Object | void
};
declare type Translator<P: {}, Component: React$ComponentType<P>> = (
WrappedComponent: Component
) => React$ComponentType<
$Diff<React$ElementConfig<Component>, TranslatorPropsVoid>
>;
declare type TranslateOptions = $Shape<{
wait: boolean,
nsMode: "default" | "fallback",
bindi18n: false | string,
bindStore: false | string,
withRef: boolean,
translateFuncName: string,
i18n: Object,
usePureComponent: boolean
}>;
declare function translate<P: {}, Component: React$ComponentType<P>>(
namespaces?: | string
| Array<string>
| (($Diff<P, TranslatorPropsVoid>) => string | Array<string>),
options?: TranslateOptions
): Translator<P, Component>;
declare type I18nProps = {
i18n?: Object,
ns?: string | Array<string>,
children: (t: TFunction, { i18n: Object, t: TFunction }) => React$Node,
initialI18nStore?: Object,
initialLanguage?: string
};
declare var I18n: React$ComponentType<I18nProps>;
declare type InterpolateProps = {
className?: string,
dangerouslySetInnerHTMLPartElement?: string,
i18n?: Object,
i18nKey?: string,
options?: Object,
parent?: string,
style?: Object,
t?: TFunction,
useDangerouslySetInnerHTML?: boolean
};
declare var Interpolate: React$ComponentType<InterpolateProps>;
declare type TransProps = {
count?: number,
parent?: string,
i18n?: Object,
i18nKey?: string,
t?: TFunction
};
declare var Trans: React$ComponentType<TransProps>;
declare type ProviderProps = { i18n: Object, children: React$Element<*> };
declare var I18nextProvider: React$ComponentType<ProviderProps>;
declare type NamespacesProps = {
components: Array<React$ComponentType<*>>,
i18n: { loadNamespaces: Function }
};
declare function loadNamespaces(props: NamespacesProps): Promise<void>;
declare var reactI18nextModule: {
type: "3rdParty",
init: (instance: Object) => void
};
declare function setDefaults(options: TranslateOptions): void;
declare function getDefaults(): TranslateOptions;
declare function getI18n(): Object;
declare function setI18n(instance: Object): void;
}

View File

@@ -12,7 +12,7 @@
"eslint-fix": "eslint src --fix"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17",
"@scm-manager/ui-bundler": "^0.0.19",
"create-index": "^2.3.0",
"enzyme": "^3.5.0",
"enzyme-adapter-react-16": "^1.3.1",

View File

@@ -1,6 +1,6 @@
//@flow
import React from "react";
import { withContextPath } from "./urls";
import {withContextPath} from "./urls";
type Props = {
src: string,

View File

@@ -48,6 +48,14 @@ class ApiClient {
return this.httpRequestWithJSONBody("PUT", url, contentType, payload);
}
head(url: string) {
let options: RequestOptions = {
method: "HEAD"
};
options = Object.assign(options, fetchOptions);
return fetch(createUrl(url), options).then(handleStatusCode);
}
delete(url: string): Promise<Response> {
let options: RequestOptions = {
method: "DELETE"

View File

@@ -0,0 +1,25 @@
//@flow
import React from "react";
import Button, { type ButtonProps } from "./Button";
import type {File} from "@scm-manager/ui-types";
type Props = {
displayName: string,
url: string
};
class DownloadButton extends React.Component<Props> {
render() {
const {displayName, url} = this.props;
return (
<a className="button is-large is-info" href={url}>
<span className="icon is-medium">
<i className="fas fa-arrow-circle-down" />
</span>
<span>{displayName}</span>
</a>
);
}
}
export default DownloadButton;

View File

@@ -7,4 +7,4 @@ export { default as DeleteButton } from "./DeleteButton.js";
export { default as EditButton } from "./EditButton.js";
export { default as RemoveEntryOfTableButton } from "./RemoveEntryOfTableButton.js";
export { default as SubmitButton } from "./SubmitButton.js";
export {default as DownloadButton} from "./DownloadButton.js";

View File

@@ -1,6 +1,6 @@
//@flow
import * as React from "react";
import { Route, Link } from "react-router-dom";
import {Link, Route} from "react-router-dom";
// TODO mostly copy of PrimaryNavigationLink

View File

@@ -1,5 +1,5 @@
// @flow
import { concat, getPageFromMatch, withEndingSlash } from "./urls";
import {concat, getPageFromMatch, withEndingSlash} from "./urls";
describe("tests for withEndingSlash", () => {

View File

@@ -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.17":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.17.tgz#949b90ca57e4268be28fcf4975bd9622f60278bb"
"@scm-manager/ui-bundler@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.19.tgz#646ab1fa1e5389fad614542215c60678fb9816ae"
dependencies:
"@babel/core" "^7.0.0"
"@babel/plugin-proposal-class-properties" "^7.0.0"

View File

@@ -14,7 +14,7 @@
"check": "flow check"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17"
"@scm-manager/ui-bundler": "^0.0.19"
},
"browserify": {
"transform": [

View File

@@ -1,5 +1,5 @@
//@flow
import type { Links } from "./hal";
import type {Links} from "./hal";
export type Permission = PermissionCreateEntry & {
_links: Links

View File

@@ -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.17":
version "0.0.17"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.17.tgz#949b90ca57e4268be28fcf4975bd9622f60278bb"
"@scm-manager/ui-bundler@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.19.tgz#646ab1fa1e5389fad614542215c60678fb9816ae"
dependencies:
"@babel/core" "^7.0.0"
"@babel/plugin-proposal-class-properties" "^7.0.0"

View File

@@ -10,19 +10,24 @@
"bulma": "^0.7.1",
"bulma-tooltip": "^2.0.2",
"classnames": "^2.2.5",
"diff2html": "^2.4.0",
"font-awesome": "^4.7.0",
"history": "^4.7.2",
"i18next": "^11.4.0",
"i18next-browser-languagedetector": "^2.2.2",
"i18next-fetch-backend": "^0.1.0",
"moment": "^2.22.2",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"node-sass": "^4.9.3",
"postcss-easy-import": "^3.0.0",
"react": "^16.4.2",
"react-diff-view": "^1.7.0",
"react-dom": "^16.4.2",
"react-i18next": "^7.9.0",
"react-jss": "^8.6.0",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"react-router-redux": "^5.0.0-alpha.9",
"react-syntax-highlighter": "^9.0.1",
"redux": "^4.0.0",
"redux-devtools-extension": "^2.13.5",
"redux-logger": "^3.0.6",
@@ -43,7 +48,7 @@
"pre-commit": "jest && flow && eslint src"
},
"devDependencies": {
"@scm-manager/ui-bundler": "^0.0.17",
"@scm-manager/ui-bundler": "^0.0.19",
"copyfiles": "^2.0.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
@@ -53,6 +58,7 @@
"node-sass": "^4.9.3",
"node-sass-chokidar": "^1.3.0",
"npm-run-all": "^4.1.3",
"postcss-easy-import": "^3.0.0",
"prettier": "^1.13.7",
"react-router-enzyme-context": "^1.2.0",
"react-test-renderer": "^16.4.1",

View File

@@ -36,5 +36,9 @@
</script>
<script src="{{ contextPath }}/vendor.bundle.js"></script>
<script src="{{ contextPath }}/scm-ui.bundle.js"></script>
{{#liveReloadURL}}
<script src="{{liveReloadURL}}"></script>
{{/liveReloadURL}}
</body>
</html>

View File

@@ -51,7 +51,11 @@
"name": "Name",
"length": "Length",
"lastModified": "Last modified",
"description": "Description"
"description": "Description",
"branch": "Branch"
},
"content": {
"downloadButton": "Download"
}
},
"changesets": {

View File

@@ -14,7 +14,7 @@ import {
modifyConfigReset
} from "../modules/config";
import { connect } from "react-redux";
import type { Config, Link } from "@scm-manager/ui-types";
import type { Config } from "@scm-manager/ui-types";
import ConfigForm from "../components/form/ConfigForm";
import { getConfigLink } from "../../modules/indexResource";

View File

@@ -22,7 +22,6 @@ import reducer, {
getConfig,
getConfigUpdatePermission
} from "./config";
import { getConfigLink } from "../../modules/indexResource";
const CONFIG_URL = "/config";
const URL = "/api/v2" + CONFIG_URL;

View File

@@ -19,9 +19,8 @@ import {
Footer,
Header
} from "@scm-manager/ui-components";
import type { Me, Link } from "@scm-manager/ui-types";
import type { Me } from "@scm-manager/ui-types";
import {
fetchIndexResources,
getConfigLink,
getFetchIndexResourcesFailure,
getGroupsLink,

View File

@@ -11,7 +11,7 @@ import {
getLogoutFailure
} from "../modules/auth";
import { Loading, ErrorPage } from "@scm-manager/ui-components";
import { fetchIndexResources, getLogoutLink } from "../modules/indexResource";
import { getLogoutLink } from "../modules/indexResource";
type Props = {
authenticated: boolean,

View File

@@ -9,8 +9,7 @@ import {
createGroup,
isCreateGroupPending,
getCreateGroupFailure,
createGroupReset,
getCreateGroupLink
createGroupReset
} from "../modules/groups";
import type { Group } from "@scm-manager/ui-types";
import type { History } from "history";

View File

@@ -14,7 +14,6 @@ import type { BrowserHistory } from "history/createBrowserHistory";
import createReduxStore from "./createReduxStore";
import { ConnectedRouter } from "react-router-redux";
import PluginLoader from "./containers/PluginLoader";
import { urls } from "@scm-manager/ui-components";

View File

@@ -7,8 +7,8 @@ import { isPending } from "./pending";
import { getFailure } from "./failure";
import {
callFetchIndexResources,
FETCH_INDEXRESOURCES_SUCCESS,
fetchIndexResources, fetchIndexResourcesPending,
fetchIndexResources,
fetchIndexResourcesPending,
fetchIndexResourcesSuccess
} from "./indexResource";
@@ -156,7 +156,7 @@ export const login = (
return apiClient
.post(loginLink, login_data)
.then(response => {
dispatch(fetchIndexResourcesPending())
dispatch(fetchIndexResourcesPending());
return callFetchIndexResources();
})
.then(response => {

View File

@@ -1,8 +1,8 @@
//@flow
import React from "react";
import { binder } from "@scm-manager/ui-extensions";
import type { Changeset } from "@scm-manager/ui-types";
import { Image } from "@scm-manager/ui-components";
import {binder} from "@scm-manager/ui-extensions";
import type {Changeset} from "@scm-manager/ui-types";
import {Image} from "@scm-manager/ui-components";
type Props = {
changeset: Changeset

View File

@@ -1,6 +1,6 @@
//@flow
import * as React from "react";
import { binder } from "@scm-manager/ui-extensions";
import {binder} from "@scm-manager/ui-extensions";
type Props = {
children: React.Node

View File

@@ -1,20 +1,18 @@
//@flow
import React from "react";
import type {
Changeset,
Repository
} from "../../../../../scm-ui-components/packages/ui-types/src/index";
import type { Changeset, Repository } from "@scm-manager/ui-types";
import { Interpolate, translate } from "react-i18next";
import injectSheet from "react-jss";
import ChangesetTag from "./ChangesetTag";
import ChangesetAuthor from "./ChangesetAuthor";
import { parseDescription } from "./changesets";
import { DateFromNow } from "../../../../../scm-ui-components/packages/ui-components/src/index";
import { DateFromNow } from "@scm-manager/ui-components";
import AvatarWrapper from "./AvatarWrapper";
import AvatarImage from "./AvatarImage";
import classNames from "classnames";
import ChangesetId from "./ChangesetId";
import type { Tag } from "@scm-manager/ui-types";
import ScmDiff from "../../containers/ScmDiff";
const styles = {
spacing: {
@@ -41,6 +39,7 @@ class ChangesetDetails extends React.Component<Props> {
const date = <DateFromNow date={changeset.date} />;
return (
<div>
<div className="content">
<h4>{description.title}</h4>
<article className="media">
@@ -74,6 +73,10 @@ class ChangesetDetails extends React.Component<Props> {
})}
</p>
</div>
<div>
<ScmDiff changeset={changeset} sideBySide={false} />
</div>
</div>
);
}

View File

@@ -1,8 +1,8 @@
//@flow
import { Link } from "react-router-dom";
import {Link} from "react-router-dom";
import React from "react";
import type { Repository, Changeset } from "@scm-manager/ui-types";
import type {Changeset, Repository} from "@scm-manager/ui-types";
type Props = {
repository: Repository,

View File

@@ -1,15 +1,15 @@
//@flow
import React from "react";
import type { Changeset, Repository, Tag } from "@scm-manager/ui-types";
import type {Changeset, Repository, Tag} from "@scm-manager/ui-types";
import classNames from "classnames";
import { translate, Interpolate } from "react-i18next";
import {Interpolate, translate} from "react-i18next";
import ChangesetId from "./ChangesetId";
import injectSheet from "react-jss";
import { DateFromNow } from "@scm-manager/ui-components";
import {DateFromNow} from "@scm-manager/ui-components";
import ChangesetAuthor from "./ChangesetAuthor";
import ChangesetTag from "./ChangesetTag";
import { compose } from "redux";
import { parseDescription } from "./changesets";
import {compose} from "redux";
import {parseDescription} from "./changesets";
import AvatarWrapper from "./AvatarWrapper";
import AvatarImage from "./AvatarImage";

View File

@@ -1,6 +1,6 @@
// @flow
import { parseDescription } from "./changesets";
import {parseDescription} from "./changesets";
describe("parseDescription tests", () => {
it("should return a description with title and message", () => {

View File

@@ -1,9 +1,9 @@
//@flow
import React from "react";
import {Link} from "react-router-dom";
import { Link } from "react-router-dom";
import injectSheet from "react-jss";
import type {Repository} from "@scm-manager/ui-types";
import {DateFromNow} from "@scm-manager/ui-components";
import type { Repository } from "@scm-manager/ui-types";
import { DateFromNow } from "@scm-manager/ui-components";
import RepositoryEntryLink from "./RepositoryEntryLink";
import classNames from "classnames";
import RepositoryAvatar from "./RepositoryAvatar";
@@ -45,7 +45,7 @@ class RepositoryEntry extends React.Component<Props> {
return (
<RepositoryEntryLink
iconClass="fa-code-branch"
to={repositoryLink + "/history"}
to={repositoryLink + "/changesets"}
/>
);
}

View File

@@ -11,7 +11,7 @@ import {
} from "../modules/changesets";
import ChangesetDetails from "../components/changesets/ChangesetDetails";
import { translate } from "react-i18next";
import { Loading, ErrorPage } from "@scm-manager/ui-components";
import { ErrorPage, Loading } from "@scm-manager/ui-components";
type Props = {
id: string,

View File

@@ -1,13 +1,8 @@
// @flow
import React from "react";
import { withRouter } from "react-router-dom";
import type {
Branch,
Changeset,
PagedCollection,
Repository
} from "@scm-manager/ui-types";
import {withRouter} from "react-router-dom";
import type {Branch, Changeset, PagedCollection, Repository} from "@scm-manager/ui-types";
import {
fetchChangesets,
getChangesets,
@@ -16,15 +11,10 @@ import {
selectListAsCollection
} from "../modules/changesets";
import { connect } from "react-redux";
import {connect} from "react-redux";
import ChangesetList from "../components/changesets/ChangesetList";
import {
ErrorNotification,
LinkPaginator,
Loading,
getPageFromMatch
} from "@scm-manager/ui-components";
import { compose } from "redux";
import {ErrorNotification, getPageFromMatch, LinkPaginator, Loading} from "@scm-manager/ui-components";
import {compose} from "redux";
type Props = {
repository: Repository,

View File

@@ -1,32 +1,19 @@
//@flow
import React from "react";
import {
deleteRepo,
fetchRepo,
getFetchRepoFailure,
getRepository,
isFetchRepoPending
} from "../modules/repos";
import {deleteRepo, fetchRepo, getFetchRepoFailure, getRepository, isFetchRepoPending} from "../modules/repos";
import { connect } from "react-redux";
import { Route, Switch } from "react-router-dom";
import type { Repository } from "@scm-manager/ui-types";
import {connect} from "react-redux";
import {Route, Switch} from "react-router-dom";
import type {Repository} from "@scm-manager/ui-types";
import {
ErrorPage,
Loading,
Navigation,
NavLink,
Page,
Section
} from "@scm-manager/ui-components";
import { translate } from "react-i18next";
import {ErrorPage, Loading, Navigation, NavLink, Page, Section} from "@scm-manager/ui-components";
import {translate} from "react-i18next";
import RepositoryDetails from "../components/RepositoryDetails";
import DeleteNavAction from "../components/DeleteNavAction";
import Edit from "../containers/Edit";
import Permissions from "../permissions/containers/Permissions";
import type { History } from "history";
import type {History} from "history";
import EditNavLink from "../components/EditNavLink";
import BranchRoot from "./ChangesetsRoot";
@@ -80,11 +67,6 @@ class RepositoryRoot extends React.Component<Props> {
this.props.deleteRepo(repository, this.deleted);
};
matchChangeset = (route: any) => {
const url = this.matchedUrl();
return route.location.pathname.match(`${url}/changeset/`);
};
matches = (route: any) => {
const url = this.matchedUrl();
const regex = new RegExp(`${url}(/branches)?/?[^/]*/changesets?.*`);
@@ -125,7 +107,7 @@ class RepositoryRoot extends React.Component<Props> {
/>
<Route
path={`${url}/permissions`}
render={props => (
render={() => (
<Permissions
namespace={this.props.repository.namespace}
repoName={this.props.repository.name}

View File

@@ -0,0 +1,51 @@
// @flow
import React from "react";
import { apiClient } from "@scm-manager/ui-components";
import type { Changeset } from "@scm-manager/ui-types";
import { Diff2Html } from "diff2html";
type Props = {
changeset: Changeset,
sideBySide: boolean
};
type State = {
diff: string,
error?: Error
};
class ScmDiff extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { diff: "" };
}
componentDidMount() {
const { changeset } = this.props;
const url = changeset._links.diff.href+"?format=GIT";
apiClient
.get(url)
.then(response => response.text())
.then(text => this.setState({ ...this.state, diff: text }))
.catch(error => this.setState({ ...this.state, error }));
}
render() {
const options = {
inputFormat: "diff",
outputFormat: this.props.sideBySide ? "side-by-side" : "line-by-line",
showFiles: false,
matching: "lines"
};
const outputHtml = Diff2Html.getPrettyHtml(this.state.diff, options);
return (
// eslint-disable-next-line react/no-danger
<div dangerouslySetInnerHTML={{ __html: outputHtml }} />
);
}
}
export default ScmDiff;

View File

@@ -1,19 +1,10 @@
// @flow
import {
FAILURE_SUFFIX,
PENDING_SUFFIX,
SUCCESS_SUFFIX
} from "../../modules/types";
import { apiClient, urls } from "@scm-manager/ui-components";
import { isPending } from "../../modules/pending";
import { getFailure } from "../../modules/failure";
import type {
Action,
Branch,
PagedCollection,
Repository
} from "@scm-manager/ui-types";
import {FAILURE_SUFFIX, PENDING_SUFFIX, SUCCESS_SUFFIX} from "../../modules/types";
import {apiClient, urls} from "@scm-manager/ui-components";
import {isPending} from "../../modules/pending";
import {getFailure} from "../../modules/failure";
import type {Action, Branch, PagedCollection, Repository} from "@scm-manager/ui-types";
export const FETCH_CHANGESETS = "scm/repos/FETCH_CHANGESETS";
export const FETCH_CHANGESETS_PENDING = `${FETCH_CHANGESETS}_${PENDING_SUFFIX}`;

View File

@@ -4,27 +4,27 @@ import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import fetchMock from "fetch-mock";
import reducer, {
FETCH_CHANGESETS,
FETCH_CHANGESETS_FAILURE,
FETCH_CHANGESETS_PENDING,
FETCH_CHANGESETS_SUCCESS,
FETCH_CHANGESET,
FETCH_CHANGESET_FAILURE,
FETCH_CHANGESET_PENDING,
FETCH_CHANGESET_SUCCESS,
FETCH_CHANGESETS,
FETCH_CHANGESETS_FAILURE,
FETCH_CHANGESETS_PENDING,
FETCH_CHANGESETS_SUCCESS,
fetchChangeset,
fetchChangesetIfNeeded,
fetchChangesets,
fetchChangesetsSuccess,
getChangesets,
getFetchChangesetsFailure,
isFetchChangesetsPending,
fetchChangeset,
getChangeset,
fetchChangesetIfNeeded,
shouldFetchChangeset,
isFetchChangesetPending,
getFetchChangesetFailure,
fetchChangesetSuccess,
selectListAsCollection
getChangeset,
getChangesets,
getFetchChangesetFailure,
getFetchChangesetsFailure,
isFetchChangesetPending,
isFetchChangesetsPending,
selectListAsCollection,
shouldFetchChangeset
} from "./changesets";
const branch = {

View File

@@ -1,12 +1,9 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Checkbox, InputField, SubmitButton } from "@scm-manager/ui-components";
import {translate} from "react-i18next";
import {Checkbox, InputField, SubmitButton} from "@scm-manager/ui-components";
import TypeSelector from "./TypeSelector";
import type {
PermissionCollection,
PermissionCreateEntry
} from "@scm-manager/ui-types";
import type {PermissionCollection, PermissionCreateEntry} from "@scm-manager/ui-types";
import * as validator from "./permissionValidation";
type Props = {

View File

@@ -1,6 +1,7 @@
// @flow
import { validation } from "@scm-manager/ui-components";
import type { PermissionCollection } from "@scm-manager/ui-types";
import {validation} from "@scm-manager/ui-components";
import type {PermissionCollection} from "@scm-manager/ui-types";
const isNameValid = validation.isNameValid;
export { isNameValid };

View File

@@ -1,16 +1,12 @@
// @flow
import { apiClient } from "@scm-manager/ui-components";
import type {Action} from "@scm-manager/ui-components";
import {apiClient} from "@scm-manager/ui-components";
import * as types from "../../../modules/types";
import type { Action } from "@scm-manager/ui-components";
import type {
PermissionCollection,
Permission,
PermissionCreateEntry
} from "@scm-manager/ui-types";
import { isPending } from "../../../modules/pending";
import { getFailure } from "../../../modules/failure";
import { Dispatch } from "redux";
import type {Permission, PermissionCollection, PermissionCreateEntry} from "@scm-manager/ui-types";
import {isPending} from "../../../modules/pending";
import {getFailure} from "../../../modules/failure";
import {Dispatch} from "redux";
export const FETCH_PERMISSIONS = "scm/permissions/FETCH_PERMISSIONS";
export const FETCH_PERMISSIONS_PENDING = `${FETCH_PERMISSIONS}_${

View File

@@ -3,44 +3,44 @@ import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import fetchMock from "fetch-mock";
import reducer, {
fetchPermissions,
fetchPermissionsSuccess,
getPermissionsOfRepo,
isFetchPermissionsPending,
getFetchPermissionsFailure,
modifyPermission,
modifyPermissionSuccess,
getModifyPermissionFailure,
isModifyPermissionPending,
createPermission,
hasCreatePermission,
deletePermission,
deletePermissionSuccess,
getDeletePermissionFailure,
isDeletePermissionPending,
getModifyPermissionsFailure,
MODIFY_PERMISSION_FAILURE,
MODIFY_PERMISSION_PENDING,
FETCH_PERMISSIONS,
FETCH_PERMISSIONS_PENDING,
FETCH_PERMISSIONS_SUCCESS,
FETCH_PERMISSIONS_FAILURE,
MODIFY_PERMISSION_SUCCESS,
MODIFY_PERMISSION,
CREATE_PERMISSION,
CREATE_PERMISSION_FAILURE,
CREATE_PERMISSION_PENDING,
CREATE_PERMISSION_SUCCESS,
CREATE_PERMISSION_FAILURE,
createPermission,
createPermissionSuccess,
DELETE_PERMISSION,
DELETE_PERMISSION_FAILURE,
DELETE_PERMISSION_PENDING,
DELETE_PERMISSION_SUCCESS,
DELETE_PERMISSION_FAILURE,
CREATE_PERMISSION,
createPermissionSuccess,
deletePermission,
deletePermissionSuccess,
FETCH_PERMISSIONS,
FETCH_PERMISSIONS_FAILURE,
FETCH_PERMISSIONS_PENDING,
FETCH_PERMISSIONS_SUCCESS,
fetchPermissions,
fetchPermissionsSuccess,
getCreatePermissionFailure,
getDeletePermissionFailure,
getDeletePermissionsFailure,
getFetchPermissionsFailure,
getModifyPermissionFailure,
getModifyPermissionsFailure,
getPermissionsOfRepo,
hasCreatePermission,
isCreatePermissionPending,
getDeletePermissionsFailure
isDeletePermissionPending,
isFetchPermissionsPending,
isModifyPermissionPending,
MODIFY_PERMISSION,
MODIFY_PERMISSION_FAILURE,
MODIFY_PERMISSION_PENDING,
MODIFY_PERMISSION_SUCCESS,
modifyPermission,
modifyPermissionSuccess
} from "./permissions";
import type { Permission, PermissionCollection } from "@scm-manager/ui-types";
import type {Permission, PermissionCollection} from "@scm-manager/ui-types";
const hitchhiker_puzzle42Permission_user_eins: Permission = {
name: "user_eins",

View File

@@ -7,7 +7,6 @@ import FileTreeLeaf from "./FileTreeLeaf";
import type { Repository, File } from "@scm-manager/ui-types";
import { ErrorNotification, Loading } from "@scm-manager/ui-components";
import {
fetchSources,
getFetchSourcesFailure,
isFetchSourcesPending,
getSources
@@ -29,7 +28,6 @@ type Props = {
revision: string,
path: string,
baseUrl: string,
fetchSources: (Repository, string, string) => void,
// context props
classes: any,
t: string => string,
@@ -49,19 +47,6 @@ export function findParent(path: string) {
}
class FileTree extends React.Component<Props> {
componentDidMount() {
const { fetchSources, repository, revision, path } = this.props;
fetchSources(repository, revision, path);
}
componentDidUpdate(prevProps) {
const { fetchSources, repository, revision, path } = this.props;
if (prevProps.revision !== revision || prevProps.path !== path) {
fetchSources(repository, revision, path);
}
}
render() {
const {
error,
@@ -167,18 +152,7 @@ const mapStateToProps = (state: any, ownProps: Props) => {
};
};
const mapDispatchToProps = dispatch => {
return {
fetchSources: (repository: Repository, revision: string, path: string) => {
dispatch(fetchSources(repository, revision, path));
}
};
};
export default compose(
withRouter,
connect(
mapStateToProps,
mapDispatchToProps
)
connect(mapStateToProps)
)(injectSheet(styles)(translate("repos")(FileTree)));

View File

@@ -49,14 +49,18 @@ class FileTreeLeaf extends React.Component<Props> {
</Link>
);
}
return <FileIcon file={file} />;
return (
<Link to={this.createLink(file)}>
<FileIcon file={file} />
</Link>
);
};
createFileName = (file: File) => {
if (file.directory) {
return <Link to={this.createLink(file)}>{file.name}</Link>;
}
return file.name;
return <Link to={this.createLink(file)}>{file.name}</Link>;
};
render() {

View File

@@ -0,0 +1,26 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import type { File } from "@scm-manager/ui-types";
import { DownloadButton } from "@scm-manager/ui-components";
type Props = {
t: string => string,
file: File
};
class DownloadViewer extends React.Component<Props> {
render() {
const { t, file } = this.props;
return (
<div className="has-text-centered">
<DownloadButton
url={file._links.self.href}
displayName={t("sources.content.downloadButton")}
/>
</div>
);
}
}
export default translate("repos")(DownloadViewer);

View File

@@ -0,0 +1,24 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import type { File } from "@scm-manager/ui-types";
type Props = {
t: string => string,
file: File
};
class ImageViewer extends React.Component<Props> {
render() {
const { file } = this.props;
return (
<div className="has-text-centered">
<figure>
<img src={file._links.self.href} alt={file._links.self.href} />
</figure>
</div>
);
}
}
export default translate("repos")(ImageViewer);

View File

@@ -0,0 +1,97 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { apiClient } from "@scm-manager/ui-components";
import type { File } from "@scm-manager/ui-types";
import { ErrorNotification, Loading } from "@scm-manager/ui-components";
import SyntaxHighlighter from "react-syntax-highlighter";
import { arduinoLight } from "react-syntax-highlighter/styles/hljs";
type Props = {
t: string => string,
file: File,
language: string
};
type State = {
content: string,
error?: Error,
loaded: boolean
};
class SourcecodeViewer extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
content: "",
loaded: false
};
}
componentDidMount() {
const { file } = this.props;
getContent(file._links.self.href)
.then(result => {
if (result.error) {
this.setState({
...this.state,
error: result.error,
loaded: true
});
} else {
this.setState({
...this.state,
content: result,
loaded: true
});
}
})
.catch(err => {});
}
render() {
const { content, error, loaded } = this.state;
const language = this.props.language;
if (error) {
return <ErrorNotification error={error} />;
}
if (!loaded) {
return <Loading />;
}
if (!content) {
return null;
}
return (
<SyntaxHighlighter
showLineNumbers="true"
language={getLanguage(language)}
style={arduinoLight}
>
{content}
</SyntaxHighlighter>
);
}
}
export function getLanguage(language: string) {
return language.toLowerCase();
}
export function getContent(url: string) {
return apiClient
.get(url)
.then(response => response.text())
.then(response => {
return response;
})
.catch(err => {
return { error: err };
});
}
export default translate("repos")(SourcecodeViewer);

View File

@@ -0,0 +1,33 @@
//@flow
import fetchMock from "fetch-mock";
import {
getContent,
getLanguage
} from "./SourcecodeViewer";
describe("get content", () => {
const CONTENT_URL = "/repositories/scmadmin/TestRepo/content/testContent";
afterEach(() => {
fetchMock.reset();
fetchMock.restore();
});
it("should return content", done => {
fetchMock.getOnce("/api/v2" + CONTENT_URL, "This is a testContent");
getContent(CONTENT_URL).then(content => {
expect(content).toBe("This is a testContent");
done();
});
});
});
describe("get correct language type", () => {
it("should return javascript", () => {
expect(getLanguage("JAVASCRIPT")).toBe("javascript");
});
it("should return nothing for plain text", () => {
expect(getLanguage("")).toBe("");
});
});

View File

@@ -0,0 +1,217 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { getSources } from "../modules/sources";
import type { Repository, File } from "@scm-manager/ui-types";
import {
ErrorNotification,
Loading,
DateFromNow
} from "@scm-manager/ui-components";
import { connect } from "react-redux";
import ImageViewer from "../components/content/ImageViewer";
import SourcecodeViewer from "../components/content/SourcecodeViewer";
import DownloadViewer from "../components/content/DownloadViewer";
import FileSize from "../components/FileSize";
import injectSheet from "react-jss";
import classNames from "classnames";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { getContentType } from "./contentType";
type Props = {
loading: boolean,
error: Error,
file: File,
repository: Repository,
revision: string,
path: string,
classes: any,
t: string => string
};
type State = {
contentType: string,
language: string,
loaded: boolean,
collapsed: boolean,
error?: Error
};
const styles = {
toCenterContent: {
display: "block"
},
pointer: {
cursor: "pointer"
}
};
class Content extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
contentType: "",
language: "",
loaded: false,
collapsed: true
};
}
componentDidMount() {
const { file } = this.props;
getContentType(file._links.self.href)
.then(result => {
if (result.error) {
this.setState({
...this.state,
error: result.error,
loaded: true
});
} else {
this.setState({
...this.state,
contentType: result.type,
language: result.language,
loaded: true
});
}
})
.catch(err => {});
}
toggleCollapse = () => {
this.setState(prevState => ({
collapsed: !prevState.collapsed
}));
};
showHeader() {
const { file, classes } = this.props;
const collapsed = this.state.collapsed;
const icon = collapsed ? "fa-angle-right" : "fa-angle-down";
const fileSize = file.directory ? "" : <FileSize bytes={file.length} />;
return (
<span className={classes.pointer} onClick={this.toggleCollapse}>
<article className="media">
<div className="media-left">
<i className={classNames("fa", icon)} />
</div>
<div className="media-content">
<div className="content">{file.name}</div>
</div>
<p className="media-right">{fileSize}</p>
</article>
</span>
);
}
showMoreInformation() {
const collapsed = this.state.collapsed;
const { classes, file, revision } = this.props;
const date = <DateFromNow date={file.lastModified} />;
const description = file.description ? (
<p>
{file.description.split("\n").map((item, key) => {
return (
<span key={key}>
{item}
<br />
</span>
);
})}
</p>
) : null;
if (!collapsed) {
return (
<div className={classNames("panel-block", classes.toCenterContent)}>
<table className="table">
<tbody>
<tr>
<td>Path</td>
<td>{file.path}</td>
</tr>
<tr>
<td>Branch</td>
<td>{revision}</td>
</tr>
<tr>
<td>Last modified</td>
<td>{date}</td>
</tr>
<tr>
<td>Description</td>
<td>{description}</td>
</tr>
</tbody>
</table>
</div>
);
}
return null;
}
showContent() {
const { file, revision } = this.props;
const { contentType, language } = this.state;
if (contentType.startsWith("image/")) {
return <ImageViewer file={file} />;
} else if (language) {
return <SourcecodeViewer file={file} language={language} />;
} else if (contentType.startsWith("text/")) {
return <SourcecodeViewer file={file} language="none" />;
} else {
return (
<ExtensionPoint
name="repos.sources.view"
props={{ file, contentType, revision }}
>
<DownloadViewer file={file} />
</ExtensionPoint>
);
}
}
render() {
const { file, classes } = this.props;
const { loaded, error } = this.state;
if (!file || !loaded) {
return <Loading />;
}
if (error) {
return <ErrorNotification error={error} />;
}
const header = this.showHeader();
const content = this.showContent();
const moreInformation = this.showMoreInformation();
return (
<div>
<nav className="panel">
<article className="panel-heading">{header}</article>
{moreInformation}
<div className={classNames("panel-block", classes.toCenterContent)}>
{content}
</div>
</nav>
</div>
);
}
}
const mapStateToProps = (state: any, ownProps: Props) => {
const { repository, revision, path } = ownProps;
const file = getSources(state, repository, revision, path);
return {
file
};
};
export default injectSheet(styles)(
connect(mapStateToProps)(translate("repos")(Content))
);

View File

@@ -13,6 +13,8 @@ import {
isFetchBranchesPending
} from "../../modules/branches";
import { compose } from "redux";
import Content from "./Content";
import { fetchSources, isDirectory } from "../modules/sources";
type Props = {
repository: Repository,
@@ -22,9 +24,11 @@ type Props = {
branches: Branch[],
revision: string,
path: string,
currentFileIsDirectory: boolean,
// dispatch props
fetchBranches: Repository => void,
fetchSources: (Repository, string, string) => void,
// Context props
history: any,
@@ -33,14 +37,26 @@ type Props = {
class Sources extends React.Component<Props> {
componentDidMount() {
const { fetchBranches, repository } = this.props;
const {
fetchBranches,
repository,
revision,
path,
fetchSources
} = this.props;
fetchBranches(repository);
fetchSources(repository, revision, path);
}
componentDidUpdate(prevProps) {
const { fetchSources, repository, revision, path } = this.props;
if (prevProps.revision !== revision || prevProps.path !== path) {
fetchSources(repository, revision, path);
}
}
branchSelected = (branch?: Branch) => {
const { baseUrl, history, path } = this.props;
let url;
if (branch) {
if (path) {
@@ -55,7 +71,15 @@ class Sources extends React.Component<Props> {
};
render() {
const { repository, baseUrl, loading, error, revision, path } = this.props;
const {
repository,
baseUrl,
loading,
error,
revision,
path,
currentFileIsDirectory
} = this.props;
if (error) {
return <ErrorNotification error={error} />;
@@ -65,6 +89,7 @@ class Sources extends React.Component<Props> {
return <Loading />;
}
if (currentFileIsDirectory) {
return (
<>
{this.renderBranchSelector()}
@@ -76,10 +101,16 @@ class Sources extends React.Component<Props> {
/>
</>
);
} else {
return (
<Content repository={repository} revision={revision} path={path} />
);
}
}
renderBranchSelector = () => {
const { repository, branches, revision } = this.props;
if (repository._links.branches) {
return (
<BranchSelector
@@ -99,10 +130,12 @@ const mapStateToProps = (state, ownProps) => {
const { repository, match } = ownProps;
const { revision, path } = match.params;
const decodedRevision = revision ? decodeURIComponent(revision) : undefined;
const loading = isFetchBranchesPending(state, repository);
const error = getFetchBranchesFailure(state, repository);
const branches = getBranches(state, repository);
const currentFileIsDirectory = decodedRevision
? isDirectory(state, repository, decodedRevision, path)
: isDirectory(state, repository, revision, path);
return {
repository,
@@ -110,7 +143,8 @@ const mapStateToProps = (state, ownProps) => {
path,
loading,
error,
branches
branches,
currentFileIsDirectory
};
};
@@ -118,6 +152,9 @@ const mapDispatchToProps = dispatch => {
return {
fetchBranches: (repository: Repository) => {
dispatch(fetchBranches(repository));
},
fetchSources: (repository: Repository, revision: string, path: string) => {
dispatch(fetchSources(repository, revision, path));
}
};
};

View File

@@ -0,0 +1,16 @@
//@flow
import { apiClient } from "@scm-manager/ui-components";
export function getContentType(url: string) {
return apiClient
.head(url)
.then(response => {
return {
type: response.headers.get("Content-Type"),
language: response.headers.get("X-Programming-Language")
};
})
.catch(err => {
return { error: err };
});
}

View File

@@ -0,0 +1,29 @@
//@flow
import fetchMock from "fetch-mock";
import { getContentType } from "./contentType";
describe("get content type", () => {
const CONTENT_URL = "/repositories/scmadmin/TestRepo/content/testContent";
afterEach(() => {
fetchMock.reset();
fetchMock.restore();
});
it("should return content", done => {
let headers = {
"Content-Type": "application/text",
"X-Programming-Language": "JAVA"
};
fetchMock.head("/api/v2" + CONTENT_URL, {
headers
});
getContentType(CONTENT_URL).then(content => {
expect(content.type).toBe("application/text");
expect(content.language).toBe("JAVA");
done();
});
});
});

View File

@@ -102,6 +102,20 @@ export default function reducer(
// selectors
export function isDirectory(
state: any,
repository: Repository,
revision: string,
path: string
): boolean {
const currentFile = getSources(state, repository, revision, path);
if (currentFile && !currentFile.directory) {
return false;
} else {
return true; //also return true if no currentFile is found since it is the "default" path
}
}
export function getSources(
state: any,
repository: Repository,

View File

@@ -1,6 +1,6 @@
// @flow
import type { Repository } from "@scm-manager/ui-types";
import type { Repository, File } from "@scm-manager/ui-types";
import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import fetchMock from "fetch-mock";
@@ -14,7 +14,8 @@ import {
isFetchSourcesPending,
default as reducer,
getSources,
fetchSourcesSuccess
fetchSourcesSuccess,
isDirectory
} from "./sources";
const sourcesUrl =
@@ -79,6 +80,21 @@ const collection = {
}
};
const noDirectory: File = {
name: "src",
path: "src",
directory: true,
length: 176,
revision: "abc",
_links: {
self: {
href:
"http://localhost:8081/scm/rest/api/v2/repositories/scm/core/sources/76aae4bb4ceacf0e88938eb5b6832738b7d537b4/src"
}
},
_embedded: collection
};
describe("sources fetch", () => {
const mockStore = configureMockStore([thunk]);
@@ -168,6 +184,28 @@ describe("reducer tests", () => {
});
describe("selector tests", () => {
it("should return false if it is no directory", () => {
const state = {
sources: {
"scm/core/abc/src/main/package.json": {
noDirectory
}
}
};
expect(
isDirectory(state, repository, "abc", "src/main/package.json")
).toBeFalsy();
});
it("should return true if it is directory", () => {
const state = {
sources: {
"scm/core/abc/src": noDirectory
}
};
expect(isDirectory(state, repository, "abc", "src")).toBe(true);
});
it("should return null", () => {
expect(getSources({}, repository)).toBeFalsy();
});
@@ -181,7 +219,7 @@ describe("selector tests", () => {
expect(getSources(state, repository)).toBe(collection);
});
it("should return the source collection without revision and path", () => {
it("should return the source collection with revision and path", () => {
const state = {
sources: {
"scm/core/abc/src/main": collection

View File

@@ -1,6 +1,7 @@
@import "bulma/sass/utilities/initial-variables";
@import "bulma/sass/utilities/functions";
$blue: #33B2E8;
// $footer-background-color
@@ -52,3 +53,5 @@ $blue: #33B2E8;
@import "@fortawesome/fontawesome-free/scss/fontawesome.scss";
$fa-font-path: "webfonts";
@import "@fortawesome/fontawesome-free/scss/solid.scss";
@import "diff2html/dist/diff2html";

File diff suppressed because it is too large Load Diff

View File

@@ -103,7 +103,6 @@
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>test</scope>
</dependency>
<!-- rest api -->

View File

@@ -0,0 +1,20 @@
package sonia.scm;
import com.google.common.collect.ImmutableMap;
import com.google.inject.servlet.ServletModule;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters;
import javax.inject.Singleton;
import java.util.Map;
public class ResteasyModule extends ServletModule {
@Override
protected void configureServlets() {
bind(HttpServletDispatcher.class).in(Singleton.class);
Map<String, String> initParams = ImmutableMap.of(ResteasyContextParameters.RESTEASY_SERVLET_MAPPING_PREFIX, "/api");
serve("/api/*").with(HttpServletDispatcher.class, initParams);
}
}

View File

@@ -126,6 +126,7 @@ public class ScmContextListener extends GuiceResteasyBootstrapServletContextList
ClassOverrides overrides = ClassOverrides.findOverrides(pluginLoader.getUberClassLoader());
List<Module> moduleList = Lists.newArrayList();
moduleList.add(new ResteasyModule());
moduleList.add(new ScmInitializerModule());
moduleList.add(new ScmEventBusModule());
moduleList.add(new EagerSingletonModule());

View File

@@ -57,5 +57,9 @@ public class TemplatingPushStateDispatcher implements PushStateDispatcher {
return request.getContextPath();
}
public String getLiveReloadURL() {
return System.getProperty("livereload.url");
}
}
}

View File

@@ -0,0 +1,43 @@
package sonia.scm.api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import sonia.scm.api.v2.resources.ErrorDto;
import sonia.scm.api.v2.resources.ExceptionWithContextToErrorDtoMapper;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import java.util.Collections;
@Provider
public class FallbackExceptionMapper implements ExceptionMapper<Exception> {
private static final Logger logger = LoggerFactory.getLogger(FallbackExceptionMapper.class);
private static final String ERROR_CODE = "CmR8GCJb31";
private final ExceptionWithContextToErrorDtoMapper mapper;
@Inject
public FallbackExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
this.mapper = mapper;
}
@Override
public Response toResponse(Exception exception) {
logger.debug("map {} to status code 500", exception);
ErrorDto errorDto = new ErrorDto();
errorDto.setMessage("internal server error");
errorDto.setContext(Collections.emptyList());
errorDto.setErrorCode(ERROR_CODE);
errorDto.setTransactionId(MDC.get("transaction_id"));
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(errorDto)
.type(VndMediaType.ERROR_TYPE)
.build();
}
}

View File

@@ -13,7 +13,7 @@ public class ContextualExceptionMapper<E extends ExceptionWithContext> implement
private static final Logger logger = LoggerFactory.getLogger(ContextualExceptionMapper.class);
private ExceptionWithContextToErrorDtoMapper mapper;
private final ExceptionWithContextToErrorDtoMapper mapper;
private final Response.Status status;
private final Class<E> type;

View File

@@ -0,0 +1,17 @@
package sonia.scm.api.v2;
import sonia.scm.NotSupportedFeatureException;
import sonia.scm.api.rest.ContextualExceptionMapper;
import sonia.scm.api.v2.resources.ExceptionWithContextToErrorDtoMapper;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
@Provider
public class NotSupportedFeatureExceptionMapper extends ContextualExceptionMapper<NotSupportedFeatureException> {
@Inject
public NotSupportedFeatureExceptionMapper(ExceptionWithContextToErrorDtoMapper mapper) {
super(NotSupportedFeatureException.class, Response.Status.BAD_REQUEST, mapper);
}
}

Some files were not shown because too many files have changed in this diff Show More