diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2da400d01e..271cee5909 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,20 @@ 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
+- Add tooltips to short links on repository overview ([#1441](https://github.com/scm-manager/scm-manager/pull/1441))
+- Show the date of the last commit for branches in the frontend ([#1439](https://github.com/scm-manager/scm-manager/pull/1439))
+- Unify and add description to key view across user settings ([#1440](https://github.com/scm-manager/scm-manager/pull/1440))
+
### Changed
- Send mercurial hook callbacks over separate tcp socket instead of http ([#1416](https://github.com/scm-manager/scm-manager/pull/1416))
+## [2.10.1] - 2020-11-24
+### Fixed
+- Improved logging of failures during plugin installation ([#1442](https://github.com/scm-manager/scm-manager/pull/1442))
+- Do not throw exception when plugin file does not exist on cancelled installation ([#1442](https://github.com/scm-manager/scm-manager/pull/1442))
+
## [2.10.0] - 2020-11-20
### Added
- Delete branches directly in the UI ([#1422](https://github.com/scm-manager/scm-manager/pull/1422))
@@ -419,3 +430,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[2.6.3]: https://www.scm-manager.org/download/2.6.3
[2.7.0]: https://www.scm-manager.org/download/2.7.0
[2.7.1]: https://www.scm-manager.org/download/2.7.1
+[2.8.0]: https://www.scm-manager.org/download/2.8.0
+[2.9.0]: https://www.scm-manager.org/download/2.9.0
+[2.9.1]: https://www.scm-manager.org/download/2.9.1
+[2.10.0]: https://www.scm-manager.org/download/2.10.0
+[2.10.1]: https://www.scm-manager.org/download/2.10.1
diff --git a/docs/de/user/profile/assets/api-key-overview.png b/docs/de/user/profile/assets/api-key-overview.png
index d150b8fb1b..d1fbe8f606 100644
Binary files a/docs/de/user/profile/assets/api-key-overview.png and b/docs/de/user/profile/assets/api-key-overview.png differ
diff --git a/docs/de/user/profile/index.md b/docs/de/user/profile/index.md
index 6e399bfa13..29018292d1 100644
--- a/docs/de/user/profile/index.md
+++ b/docs/de/user/profile/index.md
@@ -13,7 +13,7 @@ eingegeben werden. Danach muss das neue Passwort zweimal eingegeben werden.
## Öffentliche Schlüssel
-Zum Prüfen von Signaturen für z. B. Commits können hier die entsprechenden öffentlichen Schlüssel hinterlegt werden.
+Zum Prüfen von Signaturen für z. B. Commits können hier die entsprechenden öffentlichen GPG Schlüssel hinterlegt werden.
Zudem können hier die vom SCM-Manager erstellten Signaturschlüssel heruntergeladen werden.
## API Schlüssel
diff --git a/docs/de/user/repo/assets/repository-branch-detailView.png b/docs/de/user/repo/assets/repository-branch-detailView.png
index d671846fef..f9727d9d4f 100644
Binary files a/docs/de/user/repo/assets/repository-branch-detailView.png and b/docs/de/user/repo/assets/repository-branch-detailView.png differ
diff --git a/docs/de/user/repo/assets/repository-branches-overview.png b/docs/de/user/repo/assets/repository-branches-overview.png
index 39dcf5e424..c839e6b57c 100644
Binary files a/docs/de/user/repo/assets/repository-branches-overview.png and b/docs/de/user/repo/assets/repository-branches-overview.png differ
diff --git a/docs/de/user/repo/assets/repository-overview.png b/docs/de/user/repo/assets/repository-overview.png
index 59cf55e4d2..2454f625a3 100644
Binary files a/docs/de/user/repo/assets/repository-overview.png and b/docs/de/user/repo/assets/repository-overview.png differ
diff --git a/docs/de/user/repo/branches.md b/docs/de/user/repo/branches.md
index 17afe92924..47ac022067 100644
--- a/docs/de/user/repo/branches.md
+++ b/docs/de/user/repo/branches.md
@@ -3,9 +3,11 @@ title: Repository
subtitle: Branches
---
### Übersicht
-Auf der Branches-Übersicht sind die bereits existierenden Branches aufgeführt. Bei einem Klick auf einen Branch wird man zur Detailseite des Branches weitergeleitet.
+Auf der Branches-Übersicht sind die bereits existierenden Branches aufgeführt. Bei einem Klick auf einen Branch wird man zur Detailseite des Branches weitergeleitet.
+Die Branches sind in zwei Listen aufgeteilt: Unter "Aktive Branches" sind Branches aufgelistet, deren letzter Commit
+nicht 30 Tage älter als der Stand des Default-Branches ist. Alle älteren Branches sind in der Liste "Stale Branches" zu finden.
-Der Tag "Default" gibt an welcher Branch aktuell, als Standard-Branch dieses Repository im SCM-Manager markiert ist. Der Standard-Branch wird immer zuerst angezeigt, wenn man das Repository im SCM-Manager öffnet.
+Der Tag "Default" gibt an, welcher Branch aktuell als Standard-Branch dieses Repository im SCM-Manager markiert ist. Der Standard-Branch wird immer zuerst angezeigt, wenn man das Repository im SCM-Manager öffnet.
Alle Branches mit Ausnahme des Default Branches können über den Mülleimer-Icon unwiderruflich gelöscht werden.
Über den "Branch erstellen"-Button gelangt man zum Formular, um neue Branches anzulegen.
diff --git a/docs/de/user/user/assets/user-information.png b/docs/de/user/user/assets/user-information.png
index f5573c10e8..b79a4076c7 100644
Binary files a/docs/de/user/user/assets/user-information.png and b/docs/de/user/user/assets/user-information.png differ
diff --git a/docs/de/user/user/assets/user-settings-general.png b/docs/de/user/user/assets/user-settings-general.png
index 9fe75a3a89..9f63014b71 100644
Binary files a/docs/de/user/user/assets/user-settings-general.png and b/docs/de/user/user/assets/user-settings-general.png differ
diff --git a/docs/de/user/user/assets/user-settings-publickeys.png b/docs/de/user/user/assets/user-settings-publickeys.png
index 9761a3b044..b40d52e2a8 100644
Binary files a/docs/de/user/user/assets/user-settings-publickeys.png and b/docs/de/user/user/assets/user-settings-publickeys.png differ
diff --git a/docs/en/user/profile/assets/api-key-overview.png b/docs/en/user/profile/assets/api-key-overview.png
index d150b8fb1b..d052188103 100644
Binary files a/docs/en/user/profile/assets/api-key-overview.png and b/docs/en/user/profile/assets/api-key-overview.png differ
diff --git a/docs/en/user/profile/index.md b/docs/en/user/profile/index.md
index 50746c2f56..5895b89700 100644
--- a/docs/en/user/profile/index.md
+++ b/docs/en/user/profile/index.md
@@ -11,9 +11,9 @@ Here the password for the current account can be changed when it is a local acco
external system). To authorize the change, the current password has to be put first. Then the new password has to be
entered twice.
-## Öffentliche Schlüssel
+## Public Keys
-To check signatures for example for commits, public keys can be stored here. Additionally the keys created by
+To check signatures (for example for commits), gpg public keys can be stored here. Additionally the keys created by
SCM-Manager can be accessed here, too.
## API keys
diff --git a/docs/en/user/repo/assets/repository-branch-detailView.png b/docs/en/user/repo/assets/repository-branch-detailView.png
index 615ba696c1..28f768a6be 100644
Binary files a/docs/en/user/repo/assets/repository-branch-detailView.png and b/docs/en/user/repo/assets/repository-branch-detailView.png differ
diff --git a/docs/en/user/repo/assets/repository-branches-overview.png b/docs/en/user/repo/assets/repository-branches-overview.png
index e63ebab775..08a2ab19df 100644
Binary files a/docs/en/user/repo/assets/repository-branches-overview.png and b/docs/en/user/repo/assets/repository-branches-overview.png differ
diff --git a/docs/en/user/repo/assets/repository-overview.png b/docs/en/user/repo/assets/repository-overview.png
index 59cf55e4d2..7e6bfcbab7 100644
Binary files a/docs/en/user/repo/assets/repository-overview.png and b/docs/en/user/repo/assets/repository-overview.png differ
diff --git a/docs/en/user/repo/branches.md b/docs/en/user/repo/branches.md
index 370165710b..7a9d318786 100644
--- a/docs/en/user/repo/branches.md
+++ b/docs/en/user/repo/branches.md
@@ -4,6 +4,8 @@ subtitle: Branches
---
### Overview
The branches overview shows the branches that are already existing. By clicking on a branch, the details page of the branch is shown.
+Branches are split into two lists: Branches whose last commits are at most 30 days older than the head of the default
+branch are listed in "Active Branches". The older ones can be found in "Stale Branches".
The tag "Default" shows which branch is currently set as the default branch of the repository in SCM-Manager. The default branch is always shown first when opening the repository in SCM-Manager.
All branches except the default branch of the repository can be deleted by clicking on the trash bin icon.
diff --git a/docs/en/user/user/assets/user-information.png b/docs/en/user/user/assets/user-information.png
index f5573c10e8..666f05f7f8 100644
Binary files a/docs/en/user/user/assets/user-information.png and b/docs/en/user/user/assets/user-information.png differ
diff --git a/docs/en/user/user/assets/user-settings-general.png b/docs/en/user/user/assets/user-settings-general.png
index 4312fa0e8e..10d3688e47 100644
Binary files a/docs/en/user/user/assets/user-settings-general.png and b/docs/en/user/user/assets/user-settings-general.png differ
diff --git a/docs/en/user/user/assets/user-settings-publickeys.png b/docs/en/user/user/assets/user-settings-publickeys.png
index b2eae78e8b..286f46d8f2 100644
Binary files a/docs/en/user/user/assets/user-settings-publickeys.png and b/docs/en/user/user/assets/user-settings-publickeys.png differ
diff --git a/pom.xml b/pom.xml
index e585298b32..f25d88f521 100644
--- a/pom.xml
+++ b/pom.xml
@@ -580,7 +580,7 @@
sonia.scm.mavensmp-maven-plugin
- 1.3.0
+ 1.4.0
@@ -903,7 +903,7 @@
- 3.5.15
+ 3.6.02.15.7.0
@@ -937,7 +937,7 @@
1.10.1-scm2
- 26.0-jre
+ 30.0-jre12.16.1
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 bdcbc66a82..acfdd6a884 100644
--- a/scm-core/src/main/java/sonia/scm/repository/Branch.java
+++ b/scm-core/src/main/java/sonia/scm/repository/Branch.java
@@ -24,8 +24,6 @@
package sonia.scm.repository;
-//~--- non-JDK imports --------------------------------------------------------
-
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import sonia.scm.Validateable;
@@ -34,10 +32,9 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
+import java.util.Optional;
import java.util.regex.Pattern;
-//~--- JDK imports ------------------------------------------------------------
-
/**
* Represents a branch in a repository.
*
@@ -46,73 +43,100 @@ import java.util.regex.Pattern;
*/
@XmlRootElement(name = "branch")
@XmlAccessorType(XmlAccessType.FIELD)
-public final class Branch implements Serializable, Validateable
-{
+public final class Branch implements Serializable, Validateable {
private static final String VALID_CHARACTERS_AT_START_AND_END = "\\w-,;\\]{}@&+=$#`|<>";
private static final String VALID_CHARACTERS = VALID_CHARACTERS_AT_START_AND_END + "/.";
public static final String VALID_BRANCH_NAMES = "[" + VALID_CHARACTERS_AT_START_AND_END + "]([" + VALID_CHARACTERS + "]*[" + VALID_CHARACTERS_AT_START_AND_END + "])?";
public static final Pattern VALID_BRANCH_NAME_PATTERN = Pattern.compile(VALID_BRANCH_NAMES);
- /** Field description */
private static final long serialVersionUID = -4602244691711222413L;
- //~--- constructors ---------------------------------------------------------
+ private String name;
+
+ private String revision;
+
+ private boolean defaultBranch;
+
+ private Long lastCommitDate;
+
+ private boolean stale = false;
/**
* Constructs a new instance of branch.
* This constructor should only be called from JAXB.
- *
*/
Branch() {}
/**
* Constructs a new branch.
*
+ * @param name name of the branch
+ * @param revision latest revision of the branch
+ * @param defaultBranch Whether this branch is the default branch for the repository
+ *
+ * @deprecated Use {@link Branch#Branch(String, String, boolean, Long)} instead.
+ */
+ @Deprecated
+ Branch(String name, String revision, boolean defaultBranch) {
+ this(name, revision, defaultBranch, null);
+ }
+
+ /**
+ * Constructs a new branch.
*
* @param name name of the branch
* @param revision latest revision of the branch
+ * @param defaultBranch Whether this branch is the default branch for the repository
+ * @param lastCommitDate The date of the commit this branch points to (if computed). May be null
*/
- Branch(String name, String revision, boolean defaultBranch)
- {
+ Branch(String name, String revision, boolean defaultBranch, Long lastCommitDate) {
this.name = name;
this.revision = revision;
this.defaultBranch = defaultBranch;
+ this.lastCommitDate = lastCommitDate;
}
+ /**
+ * @deprecated Use {@link #normalBranch(String, String, Long)} instead to set the date of the last commit, too.
+ */
+ @Deprecated
public static Branch normalBranch(String name, String revision) {
- return new Branch(name, revision, false);
+ return normalBranch(name, revision, null);
}
+ public static Branch normalBranch(String name, String revision, Long lastCommitDate) {
+ return new Branch(name, revision, false, lastCommitDate);
+ }
+
+ /**
+ * @deprecated Use {@link #defaultBranch(String, String, Long)} instead to set the date of the last commit, too.
+ */
+ @Deprecated
public static Branch defaultBranch(String name, String revision) {
- return new Branch(name, revision, true);
+ return defaultBranch(name, revision, null);
}
- //~--- methods --------------------------------------------------------------
+ public static Branch defaultBranch(String name, String revision, Long lastCommitDate) {
+ return new Branch(name, revision, true, lastCommitDate);
+ }
+
+ public void setStale(boolean stale) {
+ this.stale = stale;
+ }
@Override
public boolean isValid() {
return VALID_BRANCH_NAME_PATTERN.matcher(name).matches();
}
- /**
- * {@inheritDoc}
- *
- *
- * @param obj
- *
- * @return
- */
@Override
- public boolean equals(Object obj)
- {
- if (obj == null)
- {
+ public boolean equals(Object obj) {
+ if (obj == null) {
return false;
}
- if (getClass() != obj.getClass())
- {
+ if (getClass() != obj.getClass()) {
return false;
}
@@ -120,48 +144,31 @@ public final class Branch implements Serializable, Validateable
return Objects.equal(name, other.name)
&& Objects.equal(revision, other.revision)
- && Objects.equal(defaultBranch, other.defaultBranch);
+ && Objects.equal(defaultBranch, other.defaultBranch)
+ && Objects.equal(lastCommitDate, other.lastCommitDate);
}
- /**
- * {@inheritDoc}
- *
- *
- * @return
- */
@Override
- public int hashCode()
- {
+ public int hashCode() {
return Objects.hashCode(name, revision);
}
- /**
- * {@inheritDoc}
- *
- *
- * @return
- */
@Override
- public String toString()
- {
- //J-
+ public String toString() {
return MoreObjects.toStringHelper(this)
.add("name", name)
.add("revision", revision)
+ .add("defaultBranch", defaultBranch)
+ .add("lastCommitDate", lastCommitDate)
.toString();
- //J+
}
- //~--- get methods ----------------------------------------------------------
-
/**
* Returns the name of the branch
*
- *
* @return name of the branch
*/
- public String getName()
- {
+ public String getName() {
return name;
}
@@ -170,22 +177,27 @@ public final class Branch implements Serializable, Validateable
*
* @return latest revision of branch
*/
- public String getRevision()
- {
+ public String getRevision() {
return revision;
}
+ /**
+ * Flag whether this branch is configured as the default branch.
+ */
public boolean isDefaultBranch() {
return defaultBranch;
}
- //~--- fields ---------------------------------------------------------------
+ /**
+ * The date of the commit this branch points to, if this was computed (can be empty).
+ *
+ * @since 2.11.0
+ */
+ public Optional getLastCommitDate() {
+ return Optional.ofNullable(lastCommitDate);
+ }
- /** name of the branch */
- private String name;
-
- /** Field description */
- private String revision;
-
- private boolean defaultBranch;
+ public boolean isStale() {
+ return stale;
+ }
}
diff --git a/scm-core/src/main/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputer.java b/scm-core/src/main/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputer.java
new file mode 100644
index 0000000000..15de6663ec
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputer.java
@@ -0,0 +1,65 @@
+/*
+ * 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.Branch;
+import sonia.scm.repository.spi.BranchStaleComputer;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import static java.time.Instant.ofEpochMilli;
+
+public class BranchXDaysOlderThanDefaultStaleComputer implements BranchStaleComputer {
+
+ public static final int DEFAULT_AMOUNT_OF_DAYS = 30;
+
+ private final int amountOfDays;
+
+ public BranchXDaysOlderThanDefaultStaleComputer() {
+ this(DEFAULT_AMOUNT_OF_DAYS);
+ }
+
+ public BranchXDaysOlderThanDefaultStaleComputer(int amountOfDays) {
+ this.amountOfDays = amountOfDays;
+ }
+
+ @Override
+ @SuppressWarnings("java:S3655") // we check "isPresent" for both dates, but due to the third check sonar does not get it
+ public boolean computeStale(Branch branch, StaleContext context) {
+ Branch defaultBranch = context.getDefaultBranch();
+ if (shouldCompute(branch, defaultBranch)) {
+ Instant defaultCommitDate = ofEpochMilli(defaultBranch.getLastCommitDate().get());
+ Instant thisCommitDate = ofEpochMilli(branch.getLastCommitDate().get());
+ return thisCommitDate.plus(amountOfDays, ChronoUnit.DAYS).isBefore(defaultCommitDate);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean shouldCompute(Branch branch, Branch defaultBranch) {
+ return !branch.isDefaultBranch() && branch.getLastCommitDate().isPresent() && defaultBranch.getLastCommitDate().isPresent();
+ }
+}
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..af784f287b 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(new BranchXDaysOlderThanDefaultStaleComputer()));
}
//~--- inner classes --------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/BranchStaleComputer.java b/scm-core/src/main/java/sonia/scm/repository/spi/BranchStaleComputer.java
new file mode 100644
index 0000000000..c6324fa1cf
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/spi/BranchStaleComputer.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 lombok.Data;
+import sonia.scm.repository.Branch;
+
+public interface BranchStaleComputer {
+
+ boolean computeStale(Branch branch, StaleContext context);
+
+ @Data
+ class StaleContext {
+ private Branch defaultBranch;
+ }
+}
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..9fa28a49aa 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,33 +21,52 @@
* 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.Branch;
import java.io.IOException;
import java.util.List;
-
-//~--- JDK imports ------------------------------------------------------------
+import java.util.Optional;
/**
- *
* @author Sebastian Sdorra
* @since 1.18
*/
-public interface BranchesCommand
-{
+public interface BranchesCommand {
- /**
- * Method description
- *
- *
- * @return
- *
- * @throws IOException
- */
List getBranches() throws IOException;
+
+ default List getBranchesWithStaleFlags(BranchStaleComputer computer) throws IOException {
+ List branches = getBranches();
+ new StaleProcessor(computer, branches).process();
+ return branches;
+ }
+
+ final class StaleProcessor {
+
+ private final BranchStaleComputer computer;
+ private final List branches;
+
+ private StaleProcessor(BranchStaleComputer computer, List branches) {
+ this.computer = computer;
+ this.branches = branches;
+ }
+
+ private void process() {
+ Optional defaultBranch = branches.stream()
+ .filter(Branch::isDefaultBranch)
+ .findFirst();
+
+ defaultBranch.ifPresent(this::process);
+ }
+
+ private void process(Branch defaultBranch) {
+ BranchStaleComputer.StaleContext staleContext = new BranchStaleComputer.StaleContext();
+ staleContext.setDefaultBranch(defaultBranch);
+
+ branches.forEach(branch -> branch.setStale(computer.computeStale(branch, staleContext)));
+ }
+ }
}
diff --git a/scm-core/src/test/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputerTest.java b/scm-core/src/test/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputerTest.java
new file mode 100644
index 0000000000..12fb269162
--- /dev/null
+++ b/scm-core/src/test/java/sonia/scm/repository/api/BranchXDaysOlderThanDefaultStaleComputerTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.Test;
+import sonia.scm.repository.Branch;
+import sonia.scm.repository.spi.BranchStaleComputer;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import static java.time.Instant.now;
+import static org.assertj.core.api.Assertions.assertThat;
+import static sonia.scm.repository.Branch.defaultBranch;
+import static sonia.scm.repository.Branch.normalBranch;
+
+class BranchXDaysOlderThanDefaultStaleComputerTest {
+
+ Instant now = now();
+
+ BranchXDaysOlderThanDefaultStaleComputer computer = new BranchXDaysOlderThanDefaultStaleComputer(30);
+
+ @Test
+ void shouldTagOldBranchAsStale() {
+ long staleTime =
+ now
+ .minus(30, ChronoUnit.DAYS)
+ .minus(1, ChronoUnit.MINUTES)
+ .toEpochMilli();
+
+ Branch branch = normalBranch("hog", "42", staleTime);
+ boolean stale = computer.computeStale(branch, createStaleContext());
+
+ assertThat(stale).isTrue();
+ }
+
+ @Test
+ void shouldNotTagNotSoOldBranchAsStale() {
+ long activeTime =
+ now
+ .minus(30, ChronoUnit.DAYS)
+ .plus(1, ChronoUnit.MINUTES)
+ .toEpochMilli();
+
+ Branch branch = normalBranch("hog", "42", activeTime);
+ boolean stale = computer.computeStale(branch, createStaleContext());
+
+ assertThat(stale).isFalse();
+ }
+
+ @Test
+ void shouldNotTagDefaultBranchAsStale() {
+ long staleTime =
+ now
+ .minus(30, ChronoUnit.DAYS)
+ .minus(1, ChronoUnit.MINUTES)
+ .toEpochMilli();
+
+ Branch branch = defaultBranch("hog", "42", staleTime);
+ boolean stale = computer.computeStale(branch, createStaleContext());
+
+ assertThat(stale).isFalse();
+ }
+
+ BranchStaleComputer.StaleContext createStaleContext() {
+ BranchStaleComputer.StaleContext staleContext = new BranchStaleComputer.StaleContext();
+ staleContext.setDefaultBranch(defaultBranch("default", "23", now.toEpochMilli()));
+ return staleContext;
+ }
+}
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..4a0f9326c0
--- /dev/null
+++ b/scm-core/src/test/java/sonia/scm/repository/spi/BranchesCommandTest.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.spi;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import sonia.scm.repository.Branch;
+import sonia.scm.repository.api.BranchXDaysOlderThanDefaultStaleComputer;
+
+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(new BranchXDaysOlderThanDefaultStaleComputer());
+
+ Assertions.assertThat(branchesWithStaleFlags)
+ .extracting("stale")
+ .containsExactly(true, true, false, false);
+ }
+}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchesCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchesCommand.java
index d026affd8b..683e5d0068 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchesCommand.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitBranchesCommand.java
@@ -24,14 +24,14 @@
package sonia.scm.repository.spi;
-//~--- non-JDK imports --------------------------------------------------------
-
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.Branch;
@@ -44,12 +44,9 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
-//~--- JDK imports ------------------------------------------------------------
+import static sonia.scm.repository.GitUtil.getCommit;
+import static sonia.scm.repository.GitUtil.getCommitTime;
-/**
- *
- * @author Sebastian Sdorra
- */
public class GitBranchesCommand extends AbstractGitCommand implements BranchesCommand {
private static final Logger LOG = LoggerFactory.getLogger(GitBranchesCommand.class);
@@ -60,23 +57,22 @@ public class GitBranchesCommand extends AbstractGitCommand implements BranchesCo
super(context);
}
- //~--- get methods ----------------------------------------------------------
-
@Override
public List getBranches() throws IOException {
Git git = createGit();
String defaultBranchName = determineDefaultBranchName(git);
- try {
+ Repository repository = git.getRepository();
+ try (RevWalk refWalk = new RevWalk(repository)) {
return git
.branchList()
.call()
.stream()
- .map(ref -> createBranchObject(defaultBranchName, ref))
+ .map(ref -> createBranchObject(repository, refWalk, defaultBranchName, ref))
.collect(Collectors.toList());
} catch (GitAPIException ex) {
- throw new InternalRepositoryException(repository, "could not read branches", ex);
+ throw new InternalRepositoryException(this.repository, "could not read branches", ex);
}
}
@@ -86,21 +82,31 @@ public class GitBranchesCommand extends AbstractGitCommand implements BranchesCo
}
@Nullable
- private Branch createBranchObject(String defaultBranchName, Ref ref) {
+ private Branch createBranchObject(Repository repository, RevWalk refWalk, String defaultBranchName, Ref ref) {
String branchName = GitUtil.getBranch(ref);
if (branchName == null) {
LOG.warn("could not determine branch name for branch name {} at revision {}", ref.getName(), ref.getObjectId());
return null;
} else {
+ Long lastCommitDate = getCommitDate(repository, refWalk, branchName, ref);
if (branchName.equals(defaultBranchName)) {
- return Branch.defaultBranch(branchName, GitUtil.getId(ref.getObjectId()));
+ return Branch.defaultBranch(branchName, GitUtil.getId(ref.getObjectId()), lastCommitDate);
} else {
- return Branch.normalBranch(branchName, GitUtil.getId(ref.getObjectId()));
+ return Branch.normalBranch(branchName, GitUtil.getId(ref.getObjectId()), lastCommitDate);
}
}
}
+ private Long getCommitDate(Repository repository, RevWalk refWalk, String branchName, Ref ref) {
+ try {
+ return getCommitTime(getCommit(repository, refWalk, ref));
+ } catch (IOException e) {
+ LOG.info("failed to read commit date of branch {} with revision {}", branchName, ref.getName());
+ return null;
+ }
+ }
+
private String determineDefaultBranchName(Git git) {
String defaultBranchName = context.getConfig().getDefaultBranch();
if (Strings.isNullOrEmpty(defaultBranchName)) {
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBranchesCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBranchesCommandTest.java
index 967226012a..fddf386d92 100644
--- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBranchesCommandTest.java
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBranchesCommandTest.java
@@ -24,117 +24,26 @@
package sonia.scm.repository.spi;
-import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.ListBranchCommand;
-import org.eclipse.jgit.api.errors.GitAPIException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
+import org.junit.Test;
import sonia.scm.repository.Branch;
-import sonia.scm.repository.GitRepositoryConfig;
import java.io.IOException;
import java.util.List;
-import java.util.Optional;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Optional.of;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.lenient;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-@ExtendWith(MockitoExtension.class)
-class GitBranchesCommandTest {
-
- @Mock
- GitContext context;
- @Mock
- Git git;
- @Mock
- ListBranchCommand listBranchCommand;
- @Mock
- GitRepositoryConfig gitRepositoryConfig;
-
- GitBranchesCommand branchesCommand;
- private Ref master;
-
- @BeforeEach
- void initContext() {
- when(context.getConfig()).thenReturn(gitRepositoryConfig);
- }
-
- @BeforeEach
- void initCommand() {
- master = createRef("master", "0000");
- branchesCommand = new GitBranchesCommand(context) {
- @Override
- Git createGit() {
- return git;
- }
-
- @Override
- Optional getRepositoryHeadRef(Git git) {
- return of(master);
- }
- };
- when(git.branchList()).thenReturn(listBranchCommand);
- }
+public class GitBranchesCommandTest extends AbstractGitCommandTestBase {
@Test
- void shouldCreateEmptyListWithoutBranches() throws IOException, GitAPIException {
- when(listBranchCommand.call()).thenReturn(emptyList());
+ public void shouldReadBranches() throws IOException {
+ GitBranchesCommand branchesCommand = new GitBranchesCommand(createContext());
List branches = branchesCommand.getBranches();
- assertThat(branches).isEmpty();
- }
-
- @Test
- void shouldMapNormalBranch() throws IOException, GitAPIException {
- Ref branch = createRef("branch", "1337");
- when(listBranchCommand.call()).thenReturn(asList(branch));
-
- List branches = branchesCommand.getBranches();
-
- assertThat(branches).containsExactly(Branch.normalBranch("branch", "1337"));
- }
-
- @Test
- void shouldMarkMasterBranchWithMasterFromConfig() throws IOException, GitAPIException {
- Ref branch = createRef("branch", "1337");
- when(listBranchCommand.call()).thenReturn(asList(branch));
- when(gitRepositoryConfig.getDefaultBranch()).thenReturn("branch");
-
- List branches = branchesCommand.getBranches();
-
- assertThat(branches).containsExactlyInAnyOrder(Branch.defaultBranch("branch", "1337"));
- }
-
- @Test
- void shouldMarkMasterBranchWithMasterFromHead() throws IOException, GitAPIException {
- Ref branch = createRef("branch", "1337");
- when(listBranchCommand.call()).thenReturn(asList(branch, master));
-
- List branches = branchesCommand.getBranches();
-
- assertThat(branches).containsExactlyInAnyOrder(
- Branch.normalBranch("branch", "1337"),
- Branch.defaultBranch("master", "0000")
+ assertThat(branches).contains(
+ Branch.defaultBranch("master", "fcd0ef1831e4002ac43ea539f4094334c79ea9ec", 1339428655000L),
+ Branch.normalBranch("mergeable", "91b99de908fcd04772798a31c308a64aea1a5523", 1541586052000L),
+ Branch.normalBranch("rename", "383b954b27e052db6880d57f1c860dc208795247", 1589203061000L)
);
}
-
- private Ref createRef(String branchName, String revision) {
- Ref ref = mock(Ref.class);
- lenient().when(ref.getName()).thenReturn("refs/heads/" + branchName);
- ObjectId objectId = mock(ObjectId.class);
- lenient().when(objectId.name()).thenReturn(revision);
- lenient().when(ref.getObjectId()).thenReturn(objectId);
- return ref;
- }
}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchesCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchesCommand.java
index 22cccbc8ae..a2285bad11 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchesCommand.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgBranchesCommand.java
@@ -27,7 +27,6 @@ package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import com.aragost.javahg.Changeset;
-import com.google.common.base.Function;
import com.google.common.collect.Lists;
import sonia.scm.repository.Branch;
@@ -63,14 +62,8 @@ public class HgBranchesCommand extends AbstractCommand
List hgBranches =
com.aragost.javahg.commands.BranchesCommand.on(open()).execute();
- List branches = Lists.transform(hgBranches,
- new Function()
- {
-
- @Override
- public Branch apply(com.aragost.javahg.Branch hgBranch)
- {
+ return Lists.transform(hgBranches,
+ hgBranch -> {
String node = null;
Changeset changeset = hgBranch.getBranchTip();
@@ -79,14 +72,12 @@ public class HgBranchesCommand extends AbstractCommand
node = changeset.getNode();
}
+ long lastCommitDate = changeset.getTimestamp().getDate().getTime();
if (DEFAULT_BRANCH_NAME.equals(hgBranch.getName())) {
- return Branch.defaultBranch(hgBranch.getName(), node);
+ return Branch.defaultBranch(hgBranch.getName(), node, lastCommitDate);
} else {
- return Branch.normalBranch(hgBranch.getName(), node);
+ return Branch.normalBranch(hgBranch.getName(), node, lastCommitDate);
}
- }
- });
-
- return branches;
+ });
}
}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchesCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchesCommandTest.java
new file mode 100644
index 0000000000..a8f43eb435
--- /dev/null
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgBranchesCommandTest.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.junit.Test;
+import sonia.scm.repository.Branch;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static sonia.scm.repository.Branch.defaultBranch;
+import static sonia.scm.repository.Branch.normalBranch;
+
+public class HgBranchesCommandTest extends AbstractHgCommandTestBase {
+
+ @Test
+ public void shouldReadBranches() {
+ HgBranchesCommand command = new HgBranchesCommand(cmdContext);
+
+ List branches = command.getBranches();
+
+ assertThat(branches).contains(
+ defaultBranch("default", "2baab8e80280ef05a9aa76c49c76feca2872afb7", 1339586381000L),
+ normalBranch("test-branch", "79b6baf49711ae675568e0698d730b97ef13e84a", 1339586299000L)
+ );
+ }
+}
diff --git a/scm-ui/ui-components/src/BranchSelector.stories.tsx b/scm-ui/ui-components/src/BranchSelector.stories.tsx
index 5abc1a2202..8f59b379f0 100644
--- a/scm-ui/ui-components/src/BranchSelector.stories.tsx
+++ b/scm-ui/ui-components/src/BranchSelector.stories.tsx
@@ -24,14 +24,14 @@
import { storiesOf } from "@storybook/react";
import { BranchSelector } from "./index";
-import { Branch } from "@scm-manager/ui-types/src";
+import { Branch } from "@scm-manager/ui-types";
import * as React from "react";
import styled from "styled-components";
const master = { name: "master", revision: "1", defaultBranch: true, _links: {} };
const develop = { name: "develop", revision: "2", defaultBranch: false, _links: {} };
-const branchSelected = (branch?: Branch) => {};
+const branchSelected = (branch?: Branch) => null;
const branches = [master, develop];
@@ -42,6 +42,4 @@ const Wrapper = styled.div`
storiesOf("BranchSelector", module)
.addDecorator(storyFn => {storyFn()})
- .add("Default", () => (
-
-));
+ .add("Default", () => );
diff --git a/scm-ui/ui-components/src/OverviewPageActions.tsx b/scm-ui/ui-components/src/OverviewPageActions.tsx
index 4cbffb32ef..633bc07d52 100644
--- a/scm-ui/ui-components/src/OverviewPageActions.tsx
+++ b/scm-ui/ui-components/src/OverviewPageActions.tsx
@@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-import React from "react";
-import { withRouter, RouteComponentProps } from "react-router-dom";
+import React, { FC } from "react";
+import { useHistory, useLocation } from "react-router-dom";
import classNames from "classnames";
import { Button, DropDown, urls } from "./index";
import { FilterInput } from "./forms";
-type Props = RouteComponentProps & {
+type Props = {
showCreateButton: boolean;
currentGroup: string;
groups: string[];
@@ -35,41 +35,33 @@ type Props = RouteComponentProps & {
groupSelected: (namespace: string) => void;
label?: string;
testId?: string;
+ searchPlaceholder?: string;
};
-class OverviewPageActions extends React.Component {
- render() {
- const { history, currentGroup, groups, location, link, testId, groupSelected } = this.props;
- const groupSelector = groups && (
-