diff --git a/pom.xml b/pom.xml
index 3166c6ec75..3ab3cb82a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -439,6 +439,13 @@
smp-maven-plugin
1.0.0-alpha-6
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.2
+
+
@@ -633,7 +640,6 @@
org.apache.maven.plugins
maven-deploy-plugin
- 2.7
diff --git a/scm-core/src/main/java/sonia/scm/IllegalIdentifierChangeException.java b/scm-core/src/main/java/sonia/scm/IllegalIdentifierChangeException.java
new file mode 100644
index 0000000000..63b9d0d4fc
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/IllegalIdentifierChangeException.java
@@ -0,0 +1,21 @@
+package sonia.scm;
+
+import java.util.Collections;
+
+public class IllegalIdentifierChangeException extends BadRequestException {
+
+ private static final String CODE = "thbsUFokjk";
+
+ public IllegalIdentifierChangeException(ContextEntry.ContextBuilder context, String message) {
+ super(context.build(), message);
+ }
+
+ public IllegalIdentifierChangeException(String message) {
+ super(Collections.emptyList(), message);
+ }
+
+ @Override
+ public String getCode() {
+ return CODE;
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java
index 0dbd45d0a0..bddf9b378a 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java
@@ -184,17 +184,19 @@ public class ModifyCommandBuilder {
}
}
+ @SuppressWarnings("UnstableApiUsage") // Files only used internal
private File loadData(ByteSource data) throws IOException {
File file = createTemporaryFile();
data.copyTo(Files.asByteSink(file));
return file;
}
+ @SuppressWarnings("UnstableApiUsage") // Files and ByteStreams only used internal
private File loadData(InputStream data) throws IOException {
File file = createTemporaryFile();
- OutputStream out = Files.asByteSink(file).openBufferedStream();
- ByteStreams.copy(data, out);
- out.close();
+ try (OutputStream out = Files.asByteSink(file).openBufferedStream()) {
+ ByteStreams.copy(data, out);
+ }
return file;
}
diff --git a/scm-ui/src/containers/Main.js b/scm-ui/src/containers/Main.js
index 8c05578b6b..5e982652e8 100644
--- a/scm-ui/src/containers/Main.js
+++ b/scm-ui/src/containers/Main.js
@@ -1,16 +1,16 @@
//@flow
import React from "react";
-import {Redirect, Route, Switch, withRouter} from "react-router-dom";
-import type {Links} from "@scm-manager/ui-types";
+import { Redirect, Route, Switch, withRouter } from "react-router-dom";
+import type { Links } from "@scm-manager/ui-types";
import Overview from "../repos/containers/Overview";
import Users from "../users/containers/Users";
import Login from "../containers/Login";
import Logout from "../containers/Logout";
-import {ProtectedRoute} from "@scm-manager/ui-components";
-import {binder, ExtensionPoint} from "@scm-manager/ui-extensions";
+import { ProtectedRoute } from "@scm-manager/ui-components";
+import { binder, ExtensionPoint } from "@scm-manager/ui-extensions";
import CreateUser from "../users/containers/CreateUser";
import SingleUser from "../users/containers/SingleUser";
@@ -34,7 +34,7 @@ class Main extends React.Component {
render() {
const { authenticated, links } = this.props;
const redirectUrlFactory = binder.getExtension("main.redirect", this.props);
- let url = "/repos";
+ let url = "/repos/";
if (redirectUrlFactory) {
url = redirectUrlFactory(this.props);
}
@@ -44,9 +44,10 @@ class Main extends React.Component {
+
@@ -67,9 +68,10 @@ class Main extends React.Component {
component={RepositoryRoot}
authenticated={authenticated}
/>
+
@@ -89,10 +91,10 @@ class Main extends React.Component {
path="/user/:name"
component={SingleUser}
/>
-
+
diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java
index a7b9146d00..76371a0b54 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java
@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
import sonia.scm.ConcurrentModificationException;
+import sonia.scm.IllegalIdentifierChangeException;
import sonia.scm.Manager;
import sonia.scm.ModelObject;
import sonia.scm.NotFoundException;
@@ -11,8 +12,6 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
-import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
-
/**
* Adapter from resource http endpoints to managers, for Single resources (e.g. {@code /user/name}).
*
@@ -55,7 +54,7 @@ class SingleResourceManagerAdapter dirs = collectPluginDirectories(pluginDirectory);
+ List dirs =
+ collectPluginDirectories(pluginDirectory)
+ .stream()
+ .filter(isPluginDirectory())
+ .collect(toList());
logger.debug("process {} directories: {}", dirs.size(), dirs);
@@ -194,6 +202,10 @@ public final class PluginProcessor
return ImmutableSet.copyOf(wrappers);
}
+ private Predicate isPluginDirectory() {
+ return dir -> Files.exists(dir.resolve(DIRECTORY_METAINF).resolve("scm").resolve("plugin.xml"));
+ }
+
/**
* Method description
*
diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json
index 92b81c5772..bf534dc138 100644
--- a/scm-webapp/src/main/resources/locales/de/plugins.json
+++ b/scm-webapp/src/main/resources/locales/de/plugins.json
@@ -167,6 +167,10 @@
"CHRM7IQzo1": {
"displayName": "Änderung fehlgeschlagen",
"description": "Die Änderung ist fehlgeschlagen. Bitte wenden Sie sich an ihren Administrator für weitere Hinweise."
+ },
+ "thbsUFokjk": {
+ "displayName": "Unerlaubte Änderung eines Schlüsselwerts",
+ "description": "Ein Schlüsselwert wurde unerlaubterweise geändert."
}
},
"namespaceStrategies": {
diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json
index 3f70000624..471da10159 100644
--- a/scm-webapp/src/main/resources/locales/en/plugins.json
+++ b/scm-webapp/src/main/resources/locales/en/plugins.json
@@ -167,6 +167,10 @@
"CHRM7IQzo1": {
"displayName": "Change failed",
"description": "The change failed. Please contact your administrator for further assistance."
+ },
+ "thbsUFokjk": {
+ "displayName": "Illegal change of an identifier",
+ "description": "A identifier value has been changed in the entity. This is not allowed."
}
},
"namespaceStrategies": {
diff --git a/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java b/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java
index 0fbf7eabbc..bb518ec731 100644
--- a/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java
@@ -134,6 +134,16 @@ public class PluginProcessorTest
assertThat(plugin.getId(), is(PLUGIN_A.id));
}
+ @Test
+ public void shouldCollectPluginsAndDoNotFailOnNonPluginDirectories() throws IOException {
+ new File(pluginDirectory, "some-directory").mkdirs();
+
+ copySmp(PLUGIN_A);
+ InstalledPlugin plugin = collectAndGetFirst();
+
+ assertThat(plugin.getId(), is(PLUGIN_A.id));
+ }
+
/**
* Method description
*