diff --git a/gradle/changelog/email_for_displayuser.yaml b/gradle/changelog/email_for_displayuser.yaml new file mode 100644 index 0000000000..f0162399f2 --- /dev/null +++ b/gradle/changelog/email_for_displayuser.yaml @@ -0,0 +1,4 @@ +- type: Added + description: Internal api to determine email address for DisplayUser ([#1815](https://github.com/scm-manager/scm-manager/pull/1815)) +- type: Added + description: Set author for merge as DisplayUser ([#1815](https://github.com/scm-manager/scm-manager/pull/1815)) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java index 8fef421898..6358e72b89 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java @@ -30,6 +30,7 @@ import sonia.scm.repository.spi.MergeCommand; import sonia.scm.repository.spi.MergeCommandRequest; import sonia.scm.repository.spi.MergeConflictResult; import sonia.scm.repository.util.AuthorUtil; +import sonia.scm.user.DisplayUser; import sonia.scm.user.EMail; import javax.annotation.Nullable; @@ -131,18 +132,36 @@ public class MergeCommandBuilder { } /** - * Use this to set the author of the merge commit manually. If this is omitted, the currently logged in user will be + * Use this to set the author of the merge commit manually. If this is omitted, the currently logged-in user will be * used instead. * * This is optional and for {@link #executeMerge()} only. * * @return This builder instance. + * @deprecated Use {@link #setAuthor(DisplayUser)} instead to enable fallback email computation. */ + @Deprecated public MergeCommandBuilder setAuthor(Person author) { request.setAuthor(author); return this; } + /** + * Use this to set the author of the merge commit manually. If this is omitted, the currently logged-in user will be + * used instead. If the given user object does not have an email address, we will use {@link EMail} to compute a + * fallback address. + * + * This is optional and for {@link #executeMerge()} only. + * + * @return This builder instance. + */ + public MergeCommandBuilder setAuthor(DisplayUser author) { + String mailAddress = eMail == null ? author.getMail() : eMail.getMailOrFallback(author); + Person person = new Person(author.getDisplayName(), mailAddress); + request.setAuthor(person); + return this; + } + /** * Disables adding a verifiable signature to the merge commit. * @return This builder instance. diff --git a/scm-core/src/main/java/sonia/scm/user/EMail.java b/scm-core/src/main/java/sonia/scm/user/EMail.java index e525b8d46c..740fd99b7f 100644 --- a/scm-core/src/main/java/sonia/scm/user/EMail.java +++ b/scm-core/src/main/java/sonia/scm/user/EMail.java @@ -50,6 +50,15 @@ public class EMail { * @return email address or fallback */ public String getMailOrFallback(User user) { + return getMailOrFallback(DisplayUser.from(user)); + } + + /** + * Returns the email address of the given user or a generated fallback address. + * @param user user to resolve address from + * @return email address or fallback + */ + public String getMailOrFallback(DisplayUser user) { if (Strings.isNullOrEmpty(user.getMail())) { if (isMailUsedAsId(user)) { return user.getId(); @@ -61,11 +70,11 @@ public class EMail { } } - private boolean isMailUsedAsId(User user) { + private boolean isMailUsedAsId(DisplayUser user) { return ValidationUtil.isMailAddressValid(user.getId()); } - private String createFallbackMail(User user) { + private String createFallbackMail(DisplayUser user) { return user.getId() + "@" + scmConfiguration.getMailDomainName(); } } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/MergeCommandBuilderTest.java b/scm-core/src/test/java/sonia/scm/repository/api/MergeCommandBuilderTest.java new file mode 100644 index 0000000000..d4d4761608 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/api/MergeCommandBuilderTest.java @@ -0,0 +1,74 @@ +/* + * 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 org.junit.jupiter.api.BeforeEach; +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 sonia.scm.repository.spi.MergeCommand; +import sonia.scm.user.DisplayUser; +import sonia.scm.user.EMail; +import sonia.scm.user.User; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MergeCommandBuilderTest { + + @Mock + private MergeCommand mergeCommand; + @Mock + private EMail eMail; + + @InjectMocks + private MergeCommandBuilder mergeCommandBuilder; + + @BeforeEach + void prepareCommandBuilder() { + mergeCommandBuilder.setBranchToMerge("irrelevant"); + mergeCommandBuilder.setTargetBranch("irrelevant"); + } + + @Test + void shouldUseMailAddressFromEMailFallback() { + User user = new User("dent", "Arthur Dent", null); + DisplayUser author = DisplayUser.from(user); + when(eMail.getMailOrFallback(author)).thenReturn("dent@hitchhiker.com"); + mergeCommandBuilder.setAuthor(author); + + mergeCommandBuilder.executeMerge(); + + verify(mergeCommand).merge(argThat(mergeCommandRequest -> { + assertThat(mergeCommandRequest.getAuthor().getMail()).isEqualTo("dent@hitchhiker.com"); + return true; + })); + } +}