diff --git a/scm-core/src/main/java/sonia/scm/repository/BranchLinkProvider.java b/scm-core/src/main/java/sonia/scm/repository/BranchLinkProvider.java new file mode 100644 index 0000000000..858b69532c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/BranchLinkProvider.java @@ -0,0 +1,41 @@ +/* + * 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; + +import sonia.scm.plugin.ExtensionPoint; + +@ExtensionPoint +public interface BranchLinkProvider { + + /** + * Returns the internal api link for the given branch of the repository. + * + * @param namespaceAndName The namespace and name of the repository. + * @param branch The name of the branch. + * + * @return Internal api link for the given branch. + */ + String get(NamespaceAndName namespaceAndName, String branch); +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DefaultBranchLinkProvider.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DefaultBranchLinkProvider.java new file mode 100644 index 0000000000..ef89027651 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/DefaultBranchLinkProvider.java @@ -0,0 +1,47 @@ +/* + * 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.api.v2.resources; + +import sonia.scm.plugin.Extension; +import sonia.scm.repository.BranchLinkProvider; +import sonia.scm.repository.NamespaceAndName; + +import javax.inject.Inject; + +@Extension +public class DefaultBranchLinkProvider implements BranchLinkProvider { + + private final ResourceLinks resourceLinks; + + @Inject + public DefaultBranchLinkProvider(ResourceLinks resourceLinks) { + this.resourceLinks = resourceLinks; + } + + @Override + public String get(NamespaceAndName namespaceAndName, String branch) { + return resourceLinks.branch().self(namespaceAndName, branch); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java index 6874d2cbd1..dca5afa806 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java @@ -37,6 +37,7 @@ import sonia.scm.PushStateDispatcher; import sonia.scm.PushStateDispatcherProvider; import sonia.scm.Undecorated; import sonia.scm.api.rest.ObjectMapperProvider; +import sonia.scm.api.v2.resources.DefaultBranchLinkProvider; import sonia.scm.cache.CacheManager; import sonia.scm.cache.GuavaCacheManager; import sonia.scm.config.ScmConfiguration; @@ -60,6 +61,7 @@ import sonia.scm.net.ahc.XmlContentTransformer; import sonia.scm.plugin.DefaultPluginManager; import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginManager; +import sonia.scm.repository.BranchLinkProvider; import sonia.scm.repository.DefaultRepositoryManager; import sonia.scm.repository.DefaultRepositoryProvider; import sonia.scm.repository.DefaultRepositoryRoleManager; @@ -234,6 +236,8 @@ class ScmServletModule extends ServletModule { bind(AccessTokenCookieIssuer.class).to(DefaultAccessTokenCookieIssuer.class); bind(PushStateDispatcher.class).toProvider(PushStateDispatcherProvider.class); + + bind(BranchLinkProvider.class).to(DefaultBranchLinkProvider.class); } private void bind(Class clazz, Class defaultImplementation) { diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DefaultBranchLinkProviderTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DefaultBranchLinkProviderTest.java new file mode 100644 index 0000000000..5e0a9d716e --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/DefaultBranchLinkProviderTest.java @@ -0,0 +1,63 @@ +/* + * 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.api.v2.resources; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryTestData; + +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DefaultBranchLinkProviderTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private ResourceLinks resourceLinks; + + @InjectMocks + private DefaultBranchLinkProvider branchLinkProvider; + + @Test + void shouldReturnBranchLink() { + when(resourceLinks.branch()).thenReturn(new ResourceLinks.BranchLinks(() -> URI.create("/"))); + Repository repository = RepositoryTestData.createHeartOfGold(); + String branch = "develop"; + + String branchLink = branchLinkProvider.get(repository.getNamespaceAndName(), branch); + + assertThat(branchLink).isEqualTo("/v2/repositories/hitchhiker/HeartOfGold/branches/develop"); + } + +}