diff --git a/CHANGELOG.md b/CHANGELOG.md index d1164a0884..9a74919a7e 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 +- Lookup command which provides further repository information ([#1415](https://github.com/scm-manager/scm-manager/pull/1415)) + ### Fixed - Error on repository initialization with least-privilege user ([#1414](https://github.com/scm-manager/scm-manager/pull/1414)) - Adhere to git quiet flag ([#1421](https://github.com/scm-manager/scm-manager/pull/1421)) 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..4a2d3e77ae 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.10.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..2c047b97eb --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/LookupCommandBuilder.java @@ -0,0 +1,51 @@ +/* + * 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; + +import java.util.Optional; + +/** + * The lookup command executes a lookup for additional repository information. + * + * @since 2.10.0 + */ +public class LookupCommandBuilder { + + private final LookupCommand lookupCommand; + + public LookupCommandBuilder(LookupCommand lookupCommand) { + this.lookupCommand = lookupCommand; + } + + public Optional lookup(Class type, String... args) { + LookupCommandRequest request = new LookupCommandRequest<>(); + 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 a6b4265239..15c2f3f523 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 @@ -430,6 +430,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.10.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..363d50ec4e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/LookupCommand.java @@ -0,0 +1,38 @@ +/* + * 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 java.util.Optional; + +public interface LookupCommand { + + /** + * Executes lookup for given parameters. + * + * @param request Arguments provided for the lookup. + * @return Result of provided type. + */ + Optional 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..0094351038 --- /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..091c9b46b3 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.10.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..ed79e40e25 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLookupCommand.java @@ -0,0 +1,64 @@ +/* + * 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.Optional; + +@Slf4j +public class SvnLookupCommand extends AbstractSvnCommand implements LookupCommand { + + protected SvnLookupCommand(SvnContext context) { + super(context); + } + + @Override + public Optional lookup(LookupCommandRequest request) { + try { + if (request.getArgs().length > 1 && "propget".equalsIgnoreCase(request.getArgs()[0])) { + return lookupProps(request); + } + } catch (SVNException e) { + log.error("Lookup failed: ", e); + } + + return Optional.empty(); + } + + private Optional lookupProps(LookupCommandRequest request) throws SVNException { + if (request.getArgs()[1].equalsIgnoreCase("uuid")) { + if (!request.getType().equals(String.class)) { + throw new IllegalArgumentException("uuid can only be returned as String"); + } + SVNRepository repository = context.open(); + return Optional.of((T) repository.getRepositoryUUID(true)); + } + log.debug("No result found on lookup"); + return Optional.empty(); + } +} 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..f948a7168f 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+ @@ -148,14 +148,21 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider return new SvnLogCommand(context); } + @Override public ModificationsCommand getModificationsCommand() { return new SvnModificationsCommand(context); } + @Override public ModifyCommand getModifyCommand() { return new SvnModifyCommand(context, workingCopyFactory); } + @Override + public LookupCommand getLookupCommand() { + return new SvnLookupCommand(context); + } + /** * Method description * 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..df4fedae92 --- /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[]{"propget"}); + + Optional result = command.lookup(request); + + assertThat(result).isNotPresent(); + } + + @Test + void shouldReturnRepositoryUUID() throws SVNException { + String uuid = "trillian-hitchhiker-42"; + when(context.open()).thenReturn(svnRepository); + when(svnRepository.getRepositoryUUID(true)).thenReturn(uuid); + + LookupCommandRequest request = new LookupCommandRequest(); + request.setType(String.class); + request.setArgs(new String[]{"propget", "uuid", "/"}); + + Optional result = command.lookup(request); + + assertThat(result).isPresent(); + assertThat(result.get()) + .isInstanceOf(String.class) + .isEqualTo(uuid); + } +}