From 8fe612cc068162c406ad866853b2bfd62f375581 Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Tue, 20 Oct 2020 10:24:31 +0200
Subject: [PATCH 01/50] create lookup command
---
.../sonia/scm/repository/api/Command.java | 7 ++-
.../repository/api/LookupCommandBuilder.java | 49 +++++++++++++++++
.../scm/repository/api/RepositoryService.java | 14 +++++
.../scm/repository/spi/LookupCommand.java | 35 ++++++++++++
.../repository/spi/LookupCommandRequest.java | 35 ++++++++++++
.../spi/RepositoryServiceProvider.java | 8 +++
.../scm/repository/spi/SvnLookupCommand.java | 55 +++++++++++++++++++
.../spi/SvnRepositoryServiceProvider.java | 4 +-
8 files changed, 205 insertions(+), 2 deletions(-)
create mode 100644 scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/LookupCommandRequest.java
create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/Command.java b/scm-core/src/main/java/sonia/scm/repository/api/Command.java
index d00c898233..5f3e060165 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/Command.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/Command.java
@@ -57,5 +57,10 @@ public enum Command
/**
* @since 2.0
*/
- MODIFICATIONS, MERGE, DIFF_RESULT, BRANCH, MODIFY;
+ MODIFICATIONS, MERGE, DIFF_RESULT, BRANCH, MODIFY,
+
+ /**
+ * @since 2.8.0
+ */
+ LOOKUP;
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
new file mode 100644
index 0000000000..bc083521ac
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.repository.api;
+
+import sonia.scm.repository.spi.LookupCommand;
+import sonia.scm.repository.spi.LookupCommandRequest;
+
+/**
+ * The lookup command executes a lookup for additional repository information.
+ *
+ * @since 2.8.0
+ */
+public class LookupCommandBuilder {
+
+ private final LookupCommand lookupCommand;
+ private final LookupCommandRequest request = new LookupCommandRequest();
+
+ public LookupCommandBuilder(LookupCommand lookupCommand) {
+ this.lookupCommand = lookupCommand;
+ }
+
+ public T lookup(Class type, String... args) {
+ request.setType(type);
+ request.setArgs(args);
+ return lookupCommand.lookup(request);
+ }
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
index aa2a41782d..f0ffcec338 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/RepositoryService.java
@@ -429,6 +429,20 @@ public final class RepositoryService implements Closeable {
return new ModifyCommandBuilder(provider.getModifyCommand(), workdirProvider, eMail);
}
+ /**
+ * The lookup command executes a lookup which returns additional information for the repository.
+ *
+ * @return instance of {@link LookupCommandBuilder}
+ * @throws CommandNotSupportedException if the command is not supported
+ * by the implementation of the repository service provider.
+ * @since 2.8.0
+ */
+ public LookupCommandBuilder getLookupCommand() {
+ LOG.debug("create lookup command for repository {}",
+ repository.getNamespaceAndName());
+ return new LookupCommandBuilder(provider.getLookupCommand());
+ }
+
/**
* Returns true if the command is supported by the repository service.
*
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
new file mode 100644
index 0000000000..5d9cf64060
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
@@ -0,0 +1,35 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.repository.spi;
+
+public interface LookupCommand {
+
+ /**
+ * Executes lookup for given parameters.
+ * @param request Arguments provided for the lookup.
+ * @return Result of provided type.
+ */
+ T lookup(LookupCommandRequest request);
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommandRequest.java
new file mode 100644
index 0000000000..a3ceb13414
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommandRequest.java
@@ -0,0 +1,35 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.repository.spi;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class LookupCommandRequest {
+ private Class> type;
+ private String[] args;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java
index 6bde899617..f5e52e294c 100644
--- a/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/RepositoryServiceProvider.java
@@ -274,4 +274,12 @@ public abstract class RepositoryServiceProvider implements Closeable
{
throw new CommandNotSupportedException(Command.MODIFY);
}
+
+ /**
+ * @since 2.8.0
+ */
+ public LookupCommand getLookupCommand()
+ {
+ throw new CommandNotSupportedException(Command.LOOKUP);
+ }
}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
new file mode 100644
index 0000000000..908d618bec
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
@@ -0,0 +1,55 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.repository.spi;
+
+import lombok.extern.slf4j.Slf4j;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.io.SVNRepository;
+
+import java.util.Arrays;
+
+@Slf4j
+public class SvnLookupCommand extends AbstractSvnCommand implements LookupCommand {
+
+ protected SvnLookupCommand(SvnContext context) {
+ super(context);
+ }
+
+ @Override
+ public T lookup(LookupCommandRequest request) {
+ try {
+ SVNRepository repository = context.open();
+ if (request.getArgs()[0].equalsIgnoreCase("props")) {
+ if (Arrays.stream(request.getArgs()).anyMatch(a -> a.equalsIgnoreCase("uuid"))) {
+ return (T) repository.getRepositoryUUID(false);
+ }
+ }
+ } catch (SVNException | ClassCastException e) {
+ log.error("Invalid lookup request", e);
+ }
+
+ return null;
+ }
+}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java
index 1548fba869..827f9dfb03 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnRepositoryServiceProvider.java
@@ -46,7 +46,7 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider
//J-
public static final Set COMMANDS = ImmutableSet.of(
Command.BLAME, Command.BROWSE, Command.CAT, Command.DIFF,
- Command.LOG, Command.BUNDLE, Command.UNBUNDLE, Command.MODIFY
+ Command.LOG, Command.BUNDLE, Command.UNBUNDLE, Command.MODIFY, Command.LOOKUP
);
//J+
@@ -156,6 +156,8 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider
return new SvnModifyCommand(context, workingCopyFactory);
}
+ public LookupCommand getLookupCommand() { return new SvnLookupCommand(context);}
+
/**
* Method description
*
From 018ebf03ba549813c11e85edb803822464872631 Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Tue, 20 Oct 2020 13:14:03 +0200
Subject: [PATCH 02/50] fix unit test
---
.../test/java/sonia/scm/api/v2/resources/MeResourceTest.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java
index 953f4638ad..e25576f2a3 100644
--- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java
+++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MeResourceTest.java
@@ -43,6 +43,7 @@ import sonia.scm.ContextEntry;
import sonia.scm.group.GroupCollector;
import sonia.scm.security.ApiKey;
import sonia.scm.security.ApiKeyService;
+import sonia.scm.user.EMail;
import sonia.scm.user.InvalidPasswordException;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
@@ -96,6 +97,9 @@ public class MeResourceTest {
@Mock
private ApiKeyService apiKeyService;
+ @Mock
+ private EMail eMail;
+
@InjectMocks
private MeDtoFactory meDtoFactory;
@InjectMocks
From c005944a5c0f2e8875e1e6e80905b7cdbea465e6 Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Tue, 20 Oct 2020 14:07:06 +0200
Subject: [PATCH 03/50] wrap lookup command result in java.util.Optional to
clarify api
---
.../repository/api/LookupCommandBuilder.java | 4 +-
.../scm/repository/spi/LookupCommand.java | 5 +-
.../scm/repository/spi/SvnLookupCommand.java | 29 ++++---
.../repository/spi/SvnLookupCommandTest.java | 80 +++++++++++++++++++
4 files changed, 107 insertions(+), 11 deletions(-)
create mode 100644 scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLookupCommandTest.java
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
index bc083521ac..61f4be80a8 100644
--- a/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
+++ b/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java
@@ -27,6 +27,8 @@ package sonia.scm.repository.api;
import sonia.scm.repository.spi.LookupCommand;
import sonia.scm.repository.spi.LookupCommandRequest;
+import java.util.Optional;
+
/**
* The lookup command executes a lookup for additional repository information.
*
@@ -41,7 +43,7 @@ public class LookupCommandBuilder {
this.lookupCommand = lookupCommand;
}
- public T lookup(Class type, String... args) {
+ public Optional lookup(Class type, String... args) {
request.setType(type);
request.setArgs(args);
return lookupCommand.lookup(request);
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
index 5d9cf64060..57cf4f7851 100644
--- a/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java
@@ -24,12 +24,15 @@
package sonia.scm.repository.spi;
+import java.util.Optional;
+
public interface LookupCommand {
/**
* Executes lookup for given parameters.
+ *
* @param request Arguments provided for the lookup.
* @return Result of provided type.
*/
- T lookup(LookupCommandRequest request);
+ Optional lookup(LookupCommandRequest request);
}
diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
index 908d618bec..336950e8cb 100644
--- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
+++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java
@@ -29,6 +29,7 @@ import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.io.SVNRepository;
import java.util.Arrays;
+import java.util.Optional;
@Slf4j
public class SvnLookupCommand extends AbstractSvnCommand implements LookupCommand {
@@ -38,18 +39,28 @@ public class SvnLookupCommand extends AbstractSvnCommand implements LookupComman
}
@Override
- public T lookup(LookupCommandRequest request) {
+ public Optional lookup(LookupCommandRequest request) {
try {
- SVNRepository repository = context.open();
- if (request.getArgs()[0].equalsIgnoreCase("props")) {
- if (Arrays.stream(request.getArgs()).anyMatch(a -> a.equalsIgnoreCase("uuid"))) {
- return (T) repository.getRepositoryUUID(false);
- }
+ if (requestContainsArg(request, "props")) {
+ return lookupProps(request);
}
- } catch (SVNException | ClassCastException e) {
- log.error("Invalid lookup request", e);
+ } catch (SVNException e) {
+ log.error("Lookup failed: ", e);
}
- return null;
+ return Optional.empty();
+ }
+
+ private Optional lookupProps(LookupCommandRequest request) throws SVNException {
+ if (requestContainsArg(request, "uuid")) {
+ SVNRepository repository = context.open();
+ return Optional.of((T) repository.getRepositoryUUID(true));
+ }
+ log.debug("No result found on lookup");
+ return Optional.empty();
+ }
+
+ private boolean requestContainsArg(LookupCommandRequest request, String props) {
+ return Arrays.stream(request.getArgs()).anyMatch(a -> a.equalsIgnoreCase(props));
}
}
diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLookupCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLookupCommandTest.java
new file mode 100644
index 0000000000..a9c3925954
--- /dev/null
+++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnLookupCommandTest.java
@@ -0,0 +1,80 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package sonia.scm.repository.spi;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.io.SVNRepository;
+
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class SvnLookupCommandTest {
+
+ @Mock
+ SvnContext context;
+
+ @Mock
+ SVNRepository svnRepository;
+
+ @InjectMocks
+ SvnLookupCommand command;
+
+ @Test
+ void shouldReturnEmptyOptional() {
+ LookupCommandRequest request = new LookupCommandRequest();
+ request.setType(String.class);
+ request.setArgs(new String[]{"props"});
+
+ Optional
+ }
+ right={ setShowConfirmAlert(true)} />}
+ />
+ >
+ );
+};
+
+export default DeleteBranch;
diff --git a/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx b/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
index f2334c5d7e..2f91c8421b 100644
--- a/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
+++ b/scm-ui/ui-webapp/src/repos/containers/EditRepo.tsx
@@ -31,7 +31,7 @@ import { History } from "history";
import { ErrorNotification } from "@scm-manager/ui-components";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { compose } from "redux";
-import DangerZone from "./DangerZone";
+import RepositoryDangerZone from "./RepositoryDangerZone";
import { getLinks } from "../../modules/indexResource";
import { urls } from "@scm-manager/ui-components";
@@ -80,7 +80,7 @@ class EditRepo extends React.Component {
}}
/>
-
+
>
);
}
diff --git a/scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx b/scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
similarity index 93%
rename from scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx
rename to scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
index 0b2bda04b9..cb883a904f 100644
--- a/scm-ui/ui-webapp/src/repos/containers/DangerZone.tsx
+++ b/scm-ui/ui-webapp/src/repos/containers/RepositoryDangerZone.tsx
@@ -35,7 +35,7 @@ type Props = {
indexLinks: Links;
};
-const DangerZoneContainer = styled.div`
+export const DangerZoneContainer = styled.div`
padding: 1.5rem 1rem;
border: 1px solid #ff6a88;
border-radius: 5px;
@@ -56,7 +56,7 @@ const DangerZoneContainer = styled.div`
}
`;
-const DangerZone: FC = ({ repository, indexLinks }) => {
+const RepositoryDangerZone: FC = ({ repository, indexLinks }) => {
const [t] = useTranslation("repos");
const dangerZone = [];
@@ -81,4 +81,4 @@ const DangerZone: FC = ({ repository, indexLinks }) => {
);
};
-export default DangerZone;
+export default RepositoryDangerZone;
From 82c43a2012d9df7337ffe7e31ba0ed8498699c79 Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Wed, 11 Nov 2020 16:07:27 +0100
Subject: [PATCH 17/50] update CHANGELOG.md
---
CHANGELOG.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 695fa92aa3..14c102dbbc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
+### Added
+- Delete branches directly in the UI ([#1422](https://github.com/scm-manager/scm-manager/pull/1422))
+
### Fixed
- Error on repository initialization with least-privilege user ([#1414](https://github.com/scm-manager/scm-manager/pull/1414))
From 77788bab01a75f6db3e7403a82a421d0e47ab6c0 Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Wed, 11 Nov 2020 16:42:09 +0100
Subject: [PATCH 18/50] cleanup
---
.../branches/containers/DeleteBranch.tsx | 41 ++++++++-----------
.../BranchCollectionToDtoMapper.java | 1 -
.../scm/api/v2/resources/ResourceLinks.java | 16 ++++----
3 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx b/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
index 2ff9ff9284..681cae1e0a 100644
--- a/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
+++ b/scm-ui/ui-webapp/src/repos/branches/containers/DeleteBranch.tsx
@@ -38,8 +38,6 @@ const DeleteBranch: FC = ({ repository, branch }: Props) => {
const [t] = useTranslation("repos");
const history = useHistory();
- console.log("branchview", repository, branch);
-
const deleteBranch = () => {
apiClient
.delete((branch._links.delete as Link).href)
@@ -51,27 +49,24 @@ const DeleteBranch: FC = ({ repository, branch }: Props) => {
return null;
}
- let confirmAlert = null;
- if (showConfirmAlert) {
- confirmAlert = (
- deleteBranch()
- },
- {
- label: t("branch.delete.confirmAlert.cancel"),
- onClick: () => null
- }
- ]}
- close={() => setShowConfirmAlert(false)}
- />
- );
- }
+ const confirmAlert = (
+ deleteBranch()
+ },
+ {
+ label: t("branch.delete.confirmAlert.cancel"),
+ onClick: () => null
+ }
+ ]}
+ close={() => setShowConfirmAlert(false)}
+ />
+ );
return (
<>
diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchCollectionToDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchCollectionToDtoMapper.java
index f102d27c4f..bb0e93f27f 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchCollectionToDtoMapper.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchCollectionToDtoMapper.java
@@ -30,7 +30,6 @@ import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Link;
import de.otto.edison.hal.Links;
import sonia.scm.repository.Branch;
-import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryPermissions;
diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
index bbb02a64fc..7bd6c353f5 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ResourceLinks.java
@@ -24,15 +24,14 @@
package sonia.scm.api.v2.resources;
-import sonia.scm.repository.NamespaceAndName;
-import sonia.scm.repository.Repository;
import sonia.scm.security.gpg.UserPublicKeyResource;
import javax.inject.Inject;
import java.net.URI;
import java.net.URISyntaxException;
-@SuppressWarnings("squid:S1192") // string literals should not be duplicated
+@SuppressWarnings("squid:S1192")
+ // string literals should not be duplicated
class ResourceLinks {
private final ScmPathInfoStore scmPathInfoStore;
@@ -274,13 +273,13 @@ class ResourceLinks {
}
AutoCompleteLinks autoComplete() {
- return new AutoCompleteLinks (scmPathInfoStore.get());
+ return new AutoCompleteLinks(scmPathInfoStore.get());
}
- static class AutoCompleteLinks {
+ static class AutoCompleteLinks {
private final LinkBuilder linkBuilder;
- AutoCompleteLinks (ScmPathInfo pathInfo) {
+ AutoCompleteLinks(ScmPathInfo pathInfo) {
linkBuilder = new LinkBuilder(pathInfo, AutoCompleteResource.class);
}
@@ -515,11 +514,11 @@ class ResourceLinks {
}
public String changesets(String namespace, String name) {
- return toTemplateParams(incomingLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("incoming").parameters().method("incomingChangesets").parameters("source","target").href());
+ return toTemplateParams(incomingLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("incoming").parameters().method("incomingChangesets").parameters("source", "target").href());
}
public String changesets(String namespace, String name, String source, String target) {
- return incomingLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("incoming").parameters().method("incomingChangesets").parameters(source,target).href();
+ return incomingLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("incoming").parameters().method("incomingChangesets").parameters(source, target).href();
}
public String diff(String namespace, String name) {
@@ -596,6 +595,7 @@ class ResourceLinks {
ModificationsLinks(ScmPathInfo pathInfo) {
modificationsLinkBuilder = new LinkBuilder(pathInfo, RepositoryRootResource.class, RepositoryResource.class, ModificationsRootResource.class);
}
+
String self(String namespace, String name, String revision) {
return modificationsLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("modifications").parameters().method("get").parameters(revision).href();
}
From 8781a9407330d220f1d62031819b748927b2f830 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?=
Date: Wed, 11 Nov 2020 17:05:26 +0100
Subject: [PATCH 19/50] Fix german translation file for repositories
---
CHANGELOG.md | 4 ++++
scm-ui/ui-webapp/public/locales/de/repos.json | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99b640e468..d0f67bfdfc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.9.1] - 2020-11-11
+### Fixed
+- German translation for repositories view
+
## [2.9.0] - 2020-11-06
### Added
- Tracing api ([#1393](https://github.com/scm-manager/scm-manager/pull/#1393))
diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json
index d3ec72b23f..d97fc9493c 100644
--- a/scm-ui/ui-webapp/public/locales/de/repos.json
+++ b/scm-ui/ui-webapp/public/locales/de/repos.json
@@ -279,4 +279,4 @@
"clickHere": "Klicken Sie hier um Ihre Datei hochzuladen.",
"dragAndDrop": "Sie können Ihre Datei auch direkt in die Dropzone ziehen."
}
-},
+}
From f93c9f3e7c7b5879e9d6f5be85bffdd42a870d3a Mon Sep 17 00:00:00 2001
From: Eduard Heimbuch
Date: Wed, 11 Nov 2020 17:10:37 +0100
Subject: [PATCH 20/50] update documentation
---
.../assets/repository-branch-detailView.png | Bin 244603 -> 91426 bytes
.../assets/repository-branches-overview.png | Bin 241949 -> 162190 bytes
docs/de/user/repo/branches.md | 3 +++
.../assets/repository-branch-detailView.png | Bin 241973 -> 82629 bytes
.../assets/repository-branches-overview.png | Bin 239533 -> 153531 bytes
docs/en/user/repo/branches.md | 2 ++
scm-ui/ui-webapp/public/locales/de/repos.json | 2 +-
7 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/docs/de/user/repo/assets/repository-branch-detailView.png b/docs/de/user/repo/assets/repository-branch-detailView.png
index a73b369e26f0e83637cc11f7b6624e324019c3ef..d671846fef9cc7410f363d59e81dec1c5a3bc798 100644
GIT binary patch
literal 91426
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