From e590a3ee68391b49b746064f1b514fe2f5facb9a Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 17 Aug 2022 12:44:59 +0200 Subject: [PATCH] Add changesets command to enable commit search (#2106) Introduce changesets command to find all changesets for a single repository. This is required to index all changesets for the commit search. --- gradle/changelog/commit_search.yaml | 2 + .../api/ChangesetsCommandBuilder.java | 91 +++++++++++++++++++ .../sonia/scm/repository/api/Command.java | 6 +- .../repository/api/HookChangesetBuilder.java | 31 ++++++- .../scm/repository/api/RepositoryService.java | 15 ++- .../scm/repository/spi/ChangesetsCommand.java | 49 ++++++++++ .../spi/ChangesetsCommandRequest.java | 29 ++++++ .../repository/spi/HookChangesetProvider.java | 16 +--- .../repository/spi/HookChangesetResponse.java | 48 +++++----- .../spi/RepositoryServiceProvider.java | 4 + .../repository/spi/HgChangesetsCommand.java | 59 ++++++++++++ .../spi/HgRepositoryServiceProvider.java | 8 +- .../spi/HgChangesetsCommandTest.java | 61 +++++++++++++ .../repository/spi/ChangesetCollector.java | 49 ++++++++++ .../repository/spi/SvnChangesetsCommand.java | 75 +++++++++++++++ .../scm/repository/spi/SvnLogCommand.java | 17 ---- .../spi/SvnRepositoryServiceProvider.java | 6 +- .../spi/SvnChangesetsCommandTest.java | 56 ++++++++++++ .../src/main/resources/config/gcache.xml | 41 +++++---- 19 files changed, 585 insertions(+), 78 deletions(-) create mode 100644 gradle/changelog/commit_search.yaml create mode 100644 scm-core/src/main/java/sonia/scm/repository/api/ChangesetsCommandBuilder.java create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommand.java create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommandRequest.java create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgChangesetsCommand.java create mode 100644 scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgChangesetsCommandTest.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/ChangesetCollector.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnChangesetsCommand.java create mode 100644 scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnChangesetsCommandTest.java diff --git a/gradle/changelog/commit_search.yaml b/gradle/changelog/commit_search.yaml new file mode 100644 index 0000000000..2a0f817b53 --- /dev/null +++ b/gradle/changelog/commit_search.yaml @@ -0,0 +1,2 @@ +- type: added + description: Changesets command to find all repository changesets ([#2106](https://github.com/scm-manager/scm-manager/pull/2106)) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ChangesetsCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/ChangesetsCommandBuilder.java new file mode 100644 index 0000000000..b0b21fcb1e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/api/ChangesetsCommandBuilder.java @@ -0,0 +1,91 @@ +/* + * 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 com.google.common.collect.Iterables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sonia.scm.cache.Cache; +import sonia.scm.cache.CacheManager; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryCacheKey; +import sonia.scm.repository.spi.ChangesetsCommand; +import sonia.scm.repository.spi.ChangesetsCommandRequest; + +import java.io.Serializable; +import java.util.Optional; + +public class ChangesetsCommandBuilder { + + static final String CACHE_NAME = "sonia.cache.cmd.changesets"; + private final Cache> cache; + private static final Logger LOG = LoggerFactory.getLogger(ChangesetsCommandBuilder.class); + + private final Repository repository; + private final ChangesetsCommand changesetsCommand; + + private final ChangesetsCommandRequest request = new ChangesetsCommandRequest(); + + public ChangesetsCommandBuilder(CacheManager cacheManager, Repository repository, ChangesetsCommand changesetsCommand) { + this.repository = repository; + this.changesetsCommand = changesetsCommand; + this.cache = cacheManager.getCache(CACHE_NAME); + } + + public Iterable getChangesets() { + CacheKey cacheKey = new CacheKey(repository); + Iterable changesets = cache.get(cacheKey); + + if (changesets == null || Iterables.isEmpty(changesets)) { + LOG.debug("Retrieve all changesets from {{}}", repository); + changesets = changesetsCommand.getChangesets(request); + cache.put(cacheKey, changesets); + } else { + LOG.debug("Use cached changesets from {{}}", repository); + } + + return changesets; + } + + public Optional getLatestChangeset() { + LOG.debug("Retrieve latest changeset from {{}}", repository); + return changesetsCommand.getLatestChangeset(); + } + + static class CacheKey implements RepositoryCacheKey, Serializable { + private final Repository repository; + + CacheKey(Repository repository) { + this.repository = repository; + } + + @Override + public String getRepositoryId() { + return repository.getId(); + } + } + +} 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 f0bb827678..55a738be86 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 @@ -87,5 +87,9 @@ public enum Command /** * @since 2.28.0 */ - BRANCH_DETAILS + BRANCH_DETAILS, + /** + * @since 2.39.0 + */ + CHANGESETS } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/HookChangesetBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/HookChangesetBuilder.java index 457fa090da..e8d1f2063f 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/HookChangesetBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/HookChangesetBuilder.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.repository.api; //~--- non-JDK imports -------------------------------------------------------- @@ -46,6 +46,8 @@ import sonia.scm.repository.spi.HookChangesetResponse; import java.io.IOException; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; /** * The {@link HookChangesetBuilder} is able to return all {@link Changeset}s @@ -147,6 +149,33 @@ public final class HookChangesetBuilder return changesets; } + public Iterable getRemovedChangesets() { + HookChangesetResponse hookChangesetResponse = provider.handleRequest(request); + Iterable changesets = hookChangesetResponse.getRemovedChangesets(); + + if (!disablePreProcessors) + { + changesets = StreamSupport.stream(changesets.spliterator(), false).map(c -> { + Changeset copy = null; + + try { + copy = DeepCopy.copy(c); + preProcessorUtil.prepareForReturn(repository, copy); + } catch (IOException ex) { + logger.error("could not create a copy of changeset", ex); + } + + if (copy == null) { + return c; + } + + return copy; + }).collect(Collectors.toList()); + } + + return changesets; + } + //~--- set methods ---------------------------------------------------------- /** 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 4f2e696946..336ae96963 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 @@ -102,11 +102,11 @@ public final class RepositoryService implements Closeable { * Constructs a new {@link RepositoryService}. This constructor should only * be called from the {@link RepositoryServiceFactory}. * - * @param cacheManager cache manager - * @param provider implementation for {@link RepositoryServiceProvider} - * @param repository the repository - * @param workdirProvider provider for workdirs - * @param eMail utility to compute email addresses if missing + * @param cacheManager cache manager + * @param provider implementation for {@link RepositoryServiceProvider} + * @param repository the repository + * @param workdirProvider provider for workdirs + * @param eMail utility to compute email addresses if missing * @param repositoryExportingCheck */ RepositoryService(CacheManager cacheManager, @@ -504,6 +504,11 @@ public final class RepositoryService implements Closeable { return new BranchDetailsCommandBuilder(repository, provider.getBranchDetailsCommand(), cacheManager); } + public ChangesetsCommandBuilder getChangesetsCommand() { + LOG.debug("create changesets command for repository {}", repository); + return new ChangesetsCommandBuilder(cacheManager, repository, provider.getChangesetsCommand()); + } + /** * Returns true if the command is supported by the repository service. * diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommand.java new file mode 100644 index 0000000000..1114290374 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommand.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.spi; + +import sonia.scm.repository.Changeset; + +import java.util.Optional; + +/** + * + * @since 2.39.0 + */ +public interface ChangesetsCommand { + /** + * Retrieve all changesets (over all branches/tags) from the repository + * @param request + * @return iterable of all changesets + */ + Iterable getChangesets(ChangesetsCommandRequest request); + + /** + * Retrieve the latest changeset (over all branches/tags) from the repository + * @return optional of latest changeset or empty + */ + Optional getLatestChangeset(); + +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommandRequest.java new file mode 100644 index 0000000000..85d5cdc3e8 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ChangesetsCommandRequest.java @@ -0,0 +1,29 @@ +/* + * 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 class ChangesetsCommandRequest { + +} diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetProvider.java b/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetProvider.java index f87f7ad364..8dc70797a5 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetProvider.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetProvider.java @@ -21,24 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.repository.spi; /** - * * @author Sebastian Sdorra * @since 1.33 */ -public interface HookChangesetProvider -{ +public interface HookChangesetProvider { - /** - * Method description - * - * - * @param request - * - * @return - */ - public HookChangesetResponse handleRequest(HookChangesetRequest request); + HookChangesetResponse handleRequest(HookChangesetRequest request); } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetResponse.java b/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetResponse.java index e791732469..d3197e7b8f 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetResponse.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/HookChangesetResponse.java @@ -21,48 +21,50 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- +package sonia.scm.repository.spi; import sonia.scm.repository.Changeset; +import static java.util.Collections.emptyList; + /** - * Response object to retrieve {@link Changeset}s during a hook. + * Response object to retrieve {@link Changeset}s during a hook. * * @author Sebastian Sdorra * @since 1.33 */ -public final class HookChangesetResponse -{ +public final class HookChangesetResponse { + private final Iterable addedChangesets; + private final Iterable removedChangesets; - /** - * Constructs a new {@link HookChangesetResponse}. - * - * - * @param changesets added changesets - */ - public HookChangesetResponse(Iterable changesets) - { - this.changesets = changesets; + public HookChangesetResponse(Iterable addedChangesets, Iterable removedChangesets) { + this.addedChangesets = addedChangesets; + this.removedChangesets = removedChangesets; + } + + public HookChangesetResponse(Iterable changesets) { + this(changesets, emptyList()); } - //~--- get methods ---------------------------------------------------------- /** * Return added changesets. * - * * @return added changesets */ - public Iterable getChangesets() - { - return changesets; + public Iterable getChangesets() { + return addedChangesets; } - //~--- fields --------------------------------------------------------------- + /** + * Return removed changesets. + * + * @return removed changesets + * @since 2.39.0 + */ + public Iterable getRemovedChangesets() { + return removedChangesets; + } - /** added changesets */ - private Iterable changesets; } 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 772bdb757d..9f78be52d7 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 @@ -318,4 +318,8 @@ public abstract class RepositoryServiceProvider implements Closeable public BranchDetailsCommand getBranchDetailsCommand() { throw new CommandNotSupportedException(Command.BRANCH_DETAILS); } + + public ChangesetsCommand getChangesetsCommand() { + throw new CommandNotSupportedException(Command.CHANGESETS); + } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgChangesetsCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgChangesetsCommand.java new file mode 100644 index 0000000000..d9c8028686 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgChangesetsCommand.java @@ -0,0 +1,59 @@ +/* + * 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 sonia.scm.repository.Changeset; +import sonia.scm.repository.spi.javahg.HgLogChangesetCommand; + +import java.util.Optional; + +import static sonia.scm.repository.spi.javahg.HgLogChangesetCommand.on; + +public class HgChangesetsCommand extends AbstractCommand implements ChangesetsCommand { + + public HgChangesetsCommand(HgCommandContext context) { + super(context); + } + + @Override + public Iterable getChangesets(ChangesetsCommandRequest request) { + org.javahg.Repository repository = open(); + HgLogChangesetCommand cmd = on(repository, context.getConfig()); + // Get all changesets between the first changeset and the repository tip, both inclusive. + cmd.rev("tip:0"); + return cmd.execute(); + } + + @Override + public Optional getLatestChangeset() { + org.javahg.Repository repository = open(); + HgLogChangesetCommand cmd = on(repository, context.getConfig()); + Changeset tip = cmd.rev("tip").single(); + if (tip != null) { + return Optional.of(tip); + } + return Optional.empty(); + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 89bd88d97a..4a75db7557 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -57,7 +57,8 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider { Command.BUNDLE, Command.UNBUNDLE, Command.FULL_HEALTH_CHECK, - Command.BRANCH_DETAILS + Command.BRANCH_DETAILS, + Command.CHANGESETS ); public static final Set FEATURES = EnumSet.of( @@ -194,4 +195,9 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider { public BranchDetailsCommand getBranchDetailsCommand() { return new HgBranchDetailsCommand(context); } + + @Override + public ChangesetsCommand getChangesetsCommand() { + return new HgChangesetsCommand(context); + } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgChangesetsCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgChangesetsCommandTest.java new file mode 100644 index 0000000000..0192209fc4 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgChangesetsCommandTest.java @@ -0,0 +1,61 @@ +/* + * 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.Test; +import sonia.scm.repository.Changeset; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HgChangesetsCommandTest extends AbstractHgCommandTestBase { + + @Test + public void getAllChangesetsFromRepository() { + Iterable changesets = createCommand() + .getChangesets(new ChangesetsCommandRequest()); + + assertThat(changesets).hasSize(13); + } + + @Test + public void getLatestChangesetFromRepository() { + Optional changeset = createCommand() + .getLatestChangeset(); + + assertThat(changeset).isPresent(); + assertThat(changeset.get().getId()).isEqualTo("67a658097e5aba664eaabb7a79a60f8d63c59b97"); + } + + private HgChangesetsCommand createCommand() { + return new HgChangesetsCommand(cmdContext); + } + + @Override + protected String getZippedRepositoryResource() { + return "sonia/scm/repository/spi/scm-hg-ahead-behind-test.zip"; + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/ChangesetCollector.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/ChangesetCollector.java new file mode 100644 index 0000000000..cc49b05563 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/ChangesetCollector.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.spi; + +import org.tmatesoft.svn.core.ISVNLogEntryHandler; +import org.tmatesoft.svn.core.SVNLogEntry; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.SvnUtil; + +import java.util.Collection; + +/** + * Collect and convert changesets. + */ +class ChangesetCollector implements ISVNLogEntryHandler { + + private final Collection changesets; + + public ChangesetCollector(Collection changesets) { + this.changesets = changesets; + } + + @Override + public void handleLogEntry(SVNLogEntry logEntry) { + changesets.add(SvnUtil.createChangeset(logEntry)); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnChangesetsCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnChangesetsCommand.java new file mode 100644 index 0000000000..a27235bf5c --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnChangesetsCommand.java @@ -0,0 +1,75 @@ +/* + * 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 com.google.common.collect.Lists; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.io.SVNRepository; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.InternalRepositoryException; + +import java.util.List; +import java.util.Optional; + +public class SvnChangesetsCommand extends AbstractSvnCommand implements ChangesetsCommand { + + SvnChangesetsCommand(SvnContext context) { + super(context); + } + + @Override + public Iterable getChangesets(ChangesetsCommandRequest request) { + try { + SVNRepository repo = open(); + long startRev = repo.getLatestRevision(); + // We ignore the changeset 0, because it doesn't have any values like author or description + long endRev = 1; + final List changesets = Lists.newArrayList(); + + repo.log(null, startRev, endRev, true, true, new ChangesetCollector(changesets)); + return changesets; + } catch (SVNException ex) { + throw new InternalRepositoryException(repository, "could not open repository", ex); + } + } + + @Override + public Optional getLatestChangeset() { + try { + SVNRepository repo = open(); + long latestRevision = repo.getLatestRevision(); + final List changesets = Lists.newArrayList(); + + repo.log(null, latestRevision, latestRevision, true, true, new ChangesetCollector(changesets)); + + if (!changesets.isEmpty()) { + return Optional.of(changesets.get(0)); + } + return Optional.empty(); + } catch (SVNException ex) { + throw new InternalRepositoryException(repository, "could not open repository", ex); + } + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java index a31ae9efb2..a7103d77e0 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnLogCommand.java @@ -179,21 +179,4 @@ public class SvnLogCommand extends AbstractSvnCommand implements LogCommand { return new ChangesetPagingResult(total, SvnUtil.createChangesets(changesetList)); } - - /** - * Collect and convert changesets. - */ - private static class ChangesetCollector implements ISVNLogEntryHandler { - - private final Collection changesets; - - public ChangesetCollector(Collection changesets) { - this.changesets = changesets; - } - - @Override - public void handleLogEntry(SVNLogEntry logEntry) { - changesets.add(SvnUtil.createChangeset(logEntry)); - } - } } 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 7b4938657f..abfadd0ce6 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 @@ -56,7 +56,8 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider { Command.LOOKUP, Command.FULL_HEALTH_CHECK, Command.MIRROR, - Command.FILE_LOCK + Command.FILE_LOCK, + Command.CHANGESETS ); public static final Set FEATURES = EnumSet.of( @@ -161,4 +162,7 @@ public class SvnRepositoryServiceProvider extends RepositoryServiceProvider { public FileLockCommand getFileLockCommand() { return new SvnFileLockCommand(context); } + + @Override + public ChangesetsCommand getChangesetsCommand() { return new SvnChangesetsCommand(context);} } diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnChangesetsCommandTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnChangesetsCommandTest.java new file mode 100644 index 0000000000..665837245f --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/repository/spi/SvnChangesetsCommandTest.java @@ -0,0 +1,56 @@ +/* + * 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.Test; +import sonia.scm.repository.Changeset; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SvnChangesetsCommandTest extends AbstractSvnCommandTestBase { + + @Test + public void getAllChangesetsFromRepository() { + Iterable changesets = createCommand().getChangesets(new ChangesetsCommandRequest()); + + assertThat(changesets).hasSize(5); + } + + @Test + public void getLatestChangesetFromRepository() { + Optional changeset = createCommand().getLatestChangeset(); + + assertThat(changeset).isPresent(); + assertThat(changeset.get().getId()).isEqualTo("5"); + } + + private SvnChangesetsCommand createCommand() + { + return new SvnChangesetsCommand(createContext()); + } + +} diff --git a/scm-webapp/src/main/resources/config/gcache.xml b/scm-webapp/src/main/resources/config/gcache.xml index 0efccc4576..bfab7a7367 100644 --- a/scm-webapp/src/main/resources/config/gcache.xml +++ b/scm-webapp/src/main/resources/config/gcache.xml @@ -24,25 +24,25 @@ --> - - - + - + - + @@ -94,7 +94,16 @@ expireAfterAccess="60000" /> - + + + @@ -103,9 +112,9 @@ maximumSize="1000" expireAfterWrite="5400" /> - + - +