From 0988ec5c7b38f90edb585bf5ea3e85df594b7faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 23 Nov 2020 17:46:28 +0100 Subject: [PATCH] Compute stale flag depending on default branch A branch should be considered as stale, when it's commit wai more than 30 days older than the commit of the default branch. --- .../java/sonia/scm/repository/Branch.java | 25 ++++--- .../api/BranchesCommandBuilder.java | 4 +- .../scm/repository/spi/BranchesCommand.java | 11 ++- .../java/sonia/scm/repository/BranchTest.java | 31 +++++--- .../repository/spi/BranchesCommandTest.java | 73 +++++++++++++++++++ 5 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 scm-core/src/test/java/sonia/scm/repository/spi/BranchesCommandTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/Branch.java b/scm-core/src/main/java/sonia/scm/repository/Branch.java index d0213a00c2..038775d716 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Branch.java +++ b/scm-core/src/main/java/sonia/scm/repository/Branch.java @@ -32,12 +32,12 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; -import java.time.Duration; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Optional; import java.util.regex.Pattern; -import static java.time.Instant.now; +import static java.time.Instant.ofEpochMilli; /** * Represents a branch in a repository. @@ -64,6 +64,8 @@ public final class Branch implements Serializable, Validateable { private Long lastCommitDate; + private boolean stale = false; + /** * Constructs a new instance of branch. * This constructor should only be called from JAXB. @@ -123,6 +125,17 @@ public final class Branch implements Serializable, Validateable { return new Branch(name, revision, true, lastCommitDate); } + @SuppressWarnings("java:S3655") // we check "isPresent" for both dates, but due to the third check sonar does not get it + public void markAsStaleDependingOn(Branch defaultBranch) { + if (!isDefaultBranch() && getLastCommitDate().isPresent() && defaultBranch.getLastCommitDate().isPresent()) { + Instant defaultCommitDate = ofEpochMilli(defaultBranch.getLastCommitDate().get()); + Instant thisCommitDate = ofEpochMilli(getLastCommitDate().get()); + stale = thisCommitDate.plus(30, ChronoUnit.DAYS).isBefore(defaultCommitDate); + } else { + stale = false; + } + } + @Override public boolean isValid() { return VALID_BRANCH_NAME_PATTERN.matcher(name).matches(); @@ -196,12 +209,6 @@ public final class Branch implements Serializable, Validateable { } public boolean isStale() { - return !isDefaultBranch() - && getLastCommitDate() - .map(Instant::ofEpochMilli) - .map(d -> Duration.between(d, now())) - .map(d -> d.toDays()) - .map(d -> d >= 14) - .orElse(false); + return stale; } } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java index 5ba45b00a0..908dcdbc7a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/BranchesCommandBuilder.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; import com.google.common.base.Objects; @@ -165,7 +165,7 @@ public final class BranchesCommandBuilder private Branches getBranchesFromCommand() throws IOException { - return new Branches(branchesCommand.getBranches()); + return new Branches(branchesCommand.getBranchesWithStaleFlags()); } //~--- inner classes -------------------------------------------------------- diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java index ae1468e768..921818c4c1 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/BranchesCommand.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.spi; //~--- non-JDK imports -------------------------------------------------------- @@ -50,4 +50,13 @@ public interface BranchesCommand * @throws IOException */ List getBranches() throws IOException; + + default List getBranchesWithStaleFlags() throws IOException { + List branches = getBranches(); + branches.stream() + .filter(Branch::isDefaultBranch) + .findFirst() + .ifPresent(defaultBranch -> branches.forEach(branch -> branch.markAsStaleDependingOn(defaultBranch))); + return branches; + } } diff --git a/scm-core/src/test/java/sonia/scm/repository/BranchTest.java b/scm-core/src/test/java/sonia/scm/repository/BranchTest.java index 113a687c9e..89828d2f65 100644 --- a/scm-core/src/test/java/sonia/scm/repository/BranchTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/BranchTest.java @@ -26,6 +26,7 @@ package sonia.scm.repository; import org.junit.jupiter.api.Test; +import java.time.Instant; import java.time.temporal.ChronoUnit; import static java.time.Instant.now; @@ -37,39 +38,45 @@ class BranchTest { @Test void shouldTagOldBranchAsStale() { - long moreThanTwoWeeksAgo = - now() - .minus(14, ChronoUnit.DAYS) + Instant now = now(); + long staleTime = + now + .minus(30, ChronoUnit.DAYS) .minus(1, ChronoUnit.MINUTES) .toEpochMilli(); - Branch branch = normalBranch("hog", "42", moreThanTwoWeeksAgo); + Branch branch = normalBranch("hog", "42", staleTime); + branch.markAsStaleDependingOn(defaultBranch("default", "23", now.toEpochMilli())); assertThat(branch.isStale()).isTrue(); } @Test void shouldNotTagNotSoOldBranchAsStale() { - long notYetTwoWeeksAgo = - now() - .minus(14, ChronoUnit.DAYS) + Instant now = now(); + long activeTime = + now + .minus(30, ChronoUnit.DAYS) .plus(1, ChronoUnit.MINUTES) .toEpochMilli(); - Branch branch = normalBranch("hog", "42", notYetTwoWeeksAgo); + Branch branch = normalBranch("hog", "42", activeTime); + branch.markAsStaleDependingOn(defaultBranch("default", "23", now.toEpochMilli())); assertThat(branch.isStale()).isFalse(); } @Test void shouldNotTagDefaultBranchAsStale() { - long moreThanTwoWeeksAgo = - now() - .minus(14, ChronoUnit.DAYS) + Instant now = now(); + long staleTime = + now + .minus(30, ChronoUnit.DAYS) .minus(1, ChronoUnit.MINUTES) .toEpochMilli(); - Branch branch = defaultBranch("hog", "42", moreThanTwoWeeksAgo); + Branch branch = defaultBranch("hog", "42", staleTime); + branch.markAsStaleDependingOn(defaultBranch("default", "23", now.toEpochMilli())); assertThat(branch.isStale()).isFalse(); } diff --git a/scm-core/src/test/java/sonia/scm/repository/spi/BranchesCommandTest.java b/scm-core/src/test/java/sonia/scm/repository/spi/BranchesCommandTest.java new file mode 100644 index 0000000000..2abb2c2326 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/repository/spi/BranchesCommandTest.java @@ -0,0 +1,73 @@ +/* + * 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.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import sonia.scm.repository.Branch; + +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; + +import static java.time.Instant.now; +import static java.util.Arrays.asList; + +class BranchesCommandTest { + + @Test + void shouldMarkEachBranchDependingOnDefaultBranch() throws IOException { + Instant now = now(); + long staleTime = + now + .minus(30, ChronoUnit.DAYS) + .minus(1, ChronoUnit.MINUTES) + .toEpochMilli(); + long activeTime = + now + .minus(30, ChronoUnit.DAYS) + .plus(1, ChronoUnit.MINUTES) + .toEpochMilli(); + + List branches = asList( + Branch.normalBranch("arthur", "42", staleTime), + Branch.normalBranch("marvin", "42", staleTime), + Branch.defaultBranch("hog", "42", now.toEpochMilli()), + Branch.normalBranch("trillian", "42", activeTime) + ); + + List branchesWithStaleFlags = new BranchesCommand() { + @Override + public List getBranches() { + return branches; + } + }.getBranchesWithStaleFlags(); + + Assertions.assertThat(branchesWithStaleFlags) + .extracting("stale") + .containsExactly(true, true, false, false); + } +}