mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 15:35:49 +01:00
add co-authors if available to changeset view
refactor ChangesetAuthor.tsx get interfaces right / fix unit test / cleanup fix table layout use Set constructor injection to bind the implementation for the new changesetTrailers API cleanup / update CHANGELOG.md cleanup fix formatting
This commit is contained in:
committed by
René Pfeuffer
parent
a712c89f6a
commit
ec57aa88fa
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- ClassLoader and Adapter parameters to typed store apis ([#1111](https://github.com/scm-manager/scm-manager/pull/1111))
|
- ClassLoader and Adapter parameters to typed store apis ([#1111](https://github.com/scm-manager/scm-manager/pull/1111))
|
||||||
- Native packaging for Debian, Red Hat, Windows, Unix, Docker and Kubernetes ([#1165](https://github.com/scm-manager/scm-manager/pull/1165))
|
- Native packaging for Debian, Red Hat, Windows, Unix, Docker and Kubernetes ([#1165](https://github.com/scm-manager/scm-manager/pull/1165))
|
||||||
- Cache for working directories ([#1166](https://github.com/scm-manager/scm-manager/pull/1166))
|
- Cache for working directories ([#1166](https://github.com/scm-manager/scm-manager/pull/1166))
|
||||||
|
- Show commit trailers in table on changeset details view ([#1169](https://github.com/scm-manager/scm-manager/pull/1169))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Correctly resolve Links in markdown files ([#1152](https://github.com/scm-manager/scm-manager/pull/1152))
|
- Correctly resolve Links in markdown files ([#1152](https://github.com/scm-manager/scm-manager/pull/1152))
|
||||||
|
|||||||
@@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
package sonia.scm.repository;
|
package sonia.scm.repository;
|
||||||
|
|
||||||
|
import sonia.scm.api.v2.resources.TrailerPersonDto;
|
||||||
import sonia.scm.plugin.ExtensionPoint;
|
import sonia.scm.plugin.ExtensionPoint;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ExtensionPoint
|
@ExtensionPoint
|
||||||
public interface ChangesetTrailerTypes {
|
public interface ChangesetTrailers {
|
||||||
|
List<TrailerPersonDto> getTrailers(Repository repository, Changeset changeset);
|
||||||
List<String> getTrailerTypes();
|
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
*/
|
*/
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Changeset } from "@scm-manager/ui-types";
|
import { Changeset } from "@scm-manager/ui-types";
|
||||||
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
|
||||||
import { WithTranslation, withTranslation } from "react-i18next";
|
import { WithTranslation, withTranslation } from "react-i18next";
|
||||||
|
|
||||||
type Props = WithTranslation & {
|
type Props = WithTranslation & {
|
||||||
@@ -53,15 +52,27 @@ class ChangesetAuthor extends React.Component<Props> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkIfCoAuthorsExists() {
|
getCoAuthorsFromChangeset() {
|
||||||
console.log(this.props.changeset.trailerPersons.filter(p => p.trailerType === "Co-authored-by").length > 0);
|
return this.props.changeset.trailerPersons.filter(p => p.trailerType === "Co-authored-by");
|
||||||
return this.props.changeset.trailerPersons.filter(p => p.trailerType === "Co-authored-by").length > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCoAuthors() {
|
renderCoAuthors() {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
|
const coAuthors = this.getCoAuthorsFromChangeset();
|
||||||
|
|
||||||
return <>{t("changeset.author.prefix")}</>;
|
if (coAuthors.length > 0) {
|
||||||
|
const authorLabel = t("changeset.coAuthor.label", { count: coAuthors.length });
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{" " + t("changeset.coAuthor.prefix") + " "}
|
||||||
|
<a title={authorLabel + ":\n" + coAuthors.map(person => "- " + person.name).join("\n")}>
|
||||||
|
{coAuthors.length + " " + authorLabel}
|
||||||
|
</a>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
withExtensionPoint(child: any) {
|
withExtensionPoint(child: any) {
|
||||||
@@ -69,14 +80,7 @@ class ChangesetAuthor extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{t("changeset.author.prefix")} {child}
|
{t("changeset.author.prefix")} {child}
|
||||||
{this.checkIfCoAuthorsExists() ? this.renderCoAuthors() : null}
|
{this.renderCoAuthors()}
|
||||||
<ExtensionPoint
|
|
||||||
name="changesets.author.suffix"
|
|
||||||
props={{
|
|
||||||
changeset: this.props.changeset
|
|
||||||
}}
|
|
||||||
renderAll={true}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,11 +89,26 @@
|
|||||||
"diffNotSupported": "Diff des Changesets wird von diesem Repositorytyp nicht unterstützt",
|
"diffNotSupported": "Diff des Changesets wird von diesem Repositorytyp nicht unterstützt",
|
||||||
"author": {
|
"author": {
|
||||||
"prefix": "Verfasst von",
|
"prefix": "Verfasst von",
|
||||||
"mailto": "Mail senden an"
|
"mailto": "Mail senden an",
|
||||||
|
"label": "Autor"
|
||||||
|
},
|
||||||
|
"coAuthor": {
|
||||||
|
"prefix": "und",
|
||||||
|
"label": "Co-Autor",
|
||||||
|
"label_plural": "Co-Autoren"
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"sources": "Sources"
|
"sources": "Sources"
|
||||||
|
},
|
||||||
|
"trailer": {
|
||||||
|
"type": {
|
||||||
|
"Reviewed-by": "Reviewer",
|
||||||
|
"Co-authored-by": "Co-Autoren",
|
||||||
|
"Committed-by": "Committed von",
|
||||||
|
"Signed-off-by": "Signiert von",
|
||||||
|
"Pushed-by": "Pushed by"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"repositoryForm": {
|
"repositoryForm": {
|
||||||
|
|||||||
@@ -89,11 +89,27 @@
|
|||||||
"diffNotSupported": "Diff of changesets is not supported by the type of repository",
|
"diffNotSupported": "Diff of changesets is not supported by the type of repository",
|
||||||
"author": {
|
"author": {
|
||||||
"prefix": "Authored by",
|
"prefix": "Authored by",
|
||||||
"mailto": "Send mail to"
|
"mailto": "Send mail to",
|
||||||
|
"label": "Author"
|
||||||
|
},
|
||||||
|
"coAuthor": {
|
||||||
|
"prefix": "and",
|
||||||
|
"label": "Co-author",
|
||||||
|
"label_plural": "Co-authors"
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"sources": "Sources"
|
"sources": "Sources"
|
||||||
|
},
|
||||||
|
"trailer": {
|
||||||
|
"type": {
|
||||||
|
"Reviewed-by": "Reviewers",
|
||||||
|
"Co-authored-by": "Co-Authors",
|
||||||
|
"Committed-by": "Commit by",
|
||||||
|
"Signed-off-by": "Signed-off",
|
||||||
|
"Pushed-by": "Pushed by"
|
||||||
|
},
|
||||||
|
"person": "Person"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"repositoryForm": {
|
"repositoryForm": {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import {
|
|||||||
AvatarImage,
|
AvatarImage,
|
||||||
AvatarWrapper,
|
AvatarWrapper,
|
||||||
Button,
|
Button,
|
||||||
ChangesetAuthor,
|
|
||||||
ChangesetDiff,
|
ChangesetDiff,
|
||||||
ChangesetId,
|
ChangesetId,
|
||||||
changesets,
|
changesets,
|
||||||
@@ -39,6 +38,7 @@ import {
|
|||||||
DateFromNow,
|
DateFromNow,
|
||||||
Level
|
Level
|
||||||
} from "@scm-manager/ui-components";
|
} from "@scm-manager/ui-components";
|
||||||
|
import { TrailerPerson } from "@scm-manager/ui-types/src/Changesets";
|
||||||
|
|
||||||
type Props = WithTranslation & {
|
type Props = WithTranslation & {
|
||||||
changeset: Changeset;
|
changeset: Changeset;
|
||||||
@@ -63,6 +63,10 @@ const BottomMarginLevel = styled(Level)`
|
|||||||
margin-bottom: 1rem !important;
|
margin-bottom: 1rem !important;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const SizedTd = styled.td`
|
||||||
|
width: 10rem;
|
||||||
|
`;
|
||||||
|
|
||||||
class ChangesetDetails extends React.Component<Props, State> {
|
class ChangesetDetails extends React.Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -71,6 +75,29 @@ class ChangesetDetails extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collectAvailableTrailerTypes() {
|
||||||
|
const { changeset } = this.props;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return [...new Set(changeset.trailerPersons.map(person => person.trailerType))];
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrailersByType(type: string) {
|
||||||
|
const { changeset } = this.props;
|
||||||
|
return changeset.trailerPersons?.filter(person => person.trailerType === type);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTrailerPersonsByType() {
|
||||||
|
const availableTrailerTypes: string[] = this.collectAvailableTrailerTypes();
|
||||||
|
|
||||||
|
let type;
|
||||||
|
let trailerPersons = [];
|
||||||
|
for (type of availableTrailerTypes) {
|
||||||
|
trailerPersons.push({ type, persons: this.getTrailersByType(type) });
|
||||||
|
}
|
||||||
|
return trailerPersons;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { changeset, repository, t } = this.props;
|
const { changeset, repository, t } = this.props;
|
||||||
const { collapsed } = this.state;
|
const { collapsed } = this.state;
|
||||||
@@ -79,6 +106,35 @@ class ChangesetDetails extends React.Component<Props, State> {
|
|||||||
const id = <ChangesetId repository={repository} changeset={changeset} link={false} />;
|
const id = <ChangesetId repository={repository} changeset={changeset} link={false} />;
|
||||||
const date = <DateFromNow date={changeset.date} />;
|
const date = <DateFromNow date={changeset.date} />;
|
||||||
|
|
||||||
|
const trailerPersons = this.getTrailerPersonsByType();
|
||||||
|
|
||||||
|
const trailerTable = (
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<SizedTd>{t("changeset.author.label") + ":"}</SizedTd>
|
||||||
|
<td>
|
||||||
|
<a title={changeset?.author?.mail} href={"mailto:" + changeset?.author?.mail}>
|
||||||
|
{changeset?.author?.name}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{trailerPersons.map(p => (
|
||||||
|
<tr>
|
||||||
|
<SizedTd>{t("changeset.trailer.type." + p.type) + ":"}</SizedTd>
|
||||||
|
<td className="shorten-text is-marginless">
|
||||||
|
{p.persons
|
||||||
|
.map(person => (
|
||||||
|
<a title={person.mail} href={"mailto:" + person.mail}>
|
||||||
|
{person.name}
|
||||||
|
</a>
|
||||||
|
))
|
||||||
|
.reduce((prev, curr) => [prev, ", ", curr])}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={classNames("content", "is-marginless")}>
|
<div className={classNames("content", "is-marginless")}>
|
||||||
@@ -101,9 +157,7 @@ class ChangesetDetails extends React.Component<Props, State> {
|
|||||||
</RightMarginP>
|
</RightMarginP>
|
||||||
</AvatarWrapper>
|
</AvatarWrapper>
|
||||||
<div className="media-content">
|
<div className="media-content">
|
||||||
<p>
|
{trailerTable}
|
||||||
<ChangesetAuthor changeset={changeset} />
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
<Trans i18nKey="repos:changeset.summary" components={[id, date]} />
|
<Trans i18nKey="repos:changeset.summary" components={[id, date]} />
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -25,7 +25,10 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import sonia.scm.repository.ChangesetTrailerTypes;
|
import sonia.scm.plugin.Extension;
|
||||||
|
import sonia.scm.repository.Changeset;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -33,24 +36,24 @@ import java.util.List;
|
|||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ChangesetTrailerExtractor {
|
@Extension
|
||||||
|
public class ChangesetDescriptionTrailers implements ChangesetTrailers {
|
||||||
|
|
||||||
private final ChangesetTrailerTypes changesetTrailerTypes;
|
private static final List<String> types = ImmutableList.of("Co-authored-by", "Reviewed-by", "Signed-off-by", "Committed-by");
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ChangesetTrailerExtractor(ChangesetTrailerTypes changesetTrailerTypes) {
|
public ChangesetDescriptionTrailers() {}
|
||||||
this.changesetTrailerTypes = changesetTrailerTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TrailerPersonDto> extractTrailersFromCommitMessage(String commitMessage) {
|
@Override
|
||||||
|
public List<TrailerPersonDto> getTrailers(Repository repository, Changeset changeset) {
|
||||||
List<TrailerPersonDto> persons = new ArrayList<>();
|
List<TrailerPersonDto> persons = new ArrayList<>();
|
||||||
|
|
||||||
try (Scanner scanner = new Scanner(commitMessage)) {
|
try (Scanner scanner = new Scanner(changeset.getDescription())) {
|
||||||
scanner.useDelimiter(Pattern.compile("[\\n;]"));
|
scanner.useDelimiter(Pattern.compile("[\\n]"));
|
||||||
while (scanner.hasNext()) {
|
while (scanner.hasNext()) {
|
||||||
String line = scanner.next();
|
String line = scanner.next();
|
||||||
|
|
||||||
for (String trailerType : changesetTrailerTypes.getTrailerTypes()) {
|
for (String trailerType : types) {
|
||||||
if (line.contains(trailerType)) {
|
if (line.contains(trailerType)) {
|
||||||
TrailerPersonDto personDto = createPersonDtoFromUser(line);
|
TrailerPersonDto personDto = createPersonDtoFromUser(line);
|
||||||
personDto.setTrailerType(trailerType);
|
personDto.setTrailerType(trailerType);
|
||||||
@@ -59,7 +62,6 @@ public class ChangesetTrailerExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return persons;
|
return persons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,12 +79,4 @@ public class ChangesetTrailerExtractor {
|
|||||||
|
|
||||||
return personDto;
|
return personDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TrailerTypes implements ChangesetTrailerTypes {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getTrailerTypes() {
|
|
||||||
return ImmutableList.of("Co-authored-by", "Reviewed-by", "Signed-off-by", "Committed-by");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -26,9 +26,15 @@ package sonia.scm.api.v2.resources;
|
|||||||
|
|
||||||
import de.otto.edison.hal.Embedded;
|
import de.otto.edison.hal.Embedded;
|
||||||
import de.otto.edison.hal.Links;
|
import de.otto.edison.hal.Links;
|
||||||
import org.mapstruct.*;
|
import org.mapstruct.AfterMapping;
|
||||||
|
import org.mapstruct.Context;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.ObjectFactory;
|
||||||
import sonia.scm.repository.Branch;
|
import sonia.scm.repository.Branch;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.Tag;
|
import sonia.scm.repository.Tag;
|
||||||
import sonia.scm.repository.api.Command;
|
import sonia.scm.repository.api.Command;
|
||||||
@@ -37,8 +43,12 @@ import sonia.scm.repository.api.RepositoryServiceFactory;
|
|||||||
import sonia.scm.web.EdisonHalAppender;
|
import sonia.scm.web.EdisonHalAppender;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static de.otto.edison.hal.Embedded.embeddedBuilder;
|
import static de.otto.edison.hal.Embedded.embeddedBuilder;
|
||||||
@@ -64,14 +74,32 @@ public abstract class DefaultChangesetToChangesetDtoMapper extends HalAppenderMa
|
|||||||
private TagCollectionToDtoMapper tagCollectionToDtoMapper;
|
private TagCollectionToDtoMapper tagCollectionToDtoMapper;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ChangesetTrailerExtractor changesetTrailerExtractor;
|
private Set<ChangesetTrailers> changesetTrailersSet;
|
||||||
|
|
||||||
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
||||||
public abstract ChangesetDto map(Changeset changeset, @Context Repository repository);
|
public abstract ChangesetDto map(Changeset changeset, @Context Repository repository);
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
void appendTrailerPersons(Changeset changeset, @MappingTarget ChangesetDto target) {
|
void appendTrailerPersons(Changeset changeset, @MappingTarget ChangesetDto target, @Context Repository repository) {
|
||||||
target.setTrailerPersons(changesetTrailerExtractor.extractTrailersFromCommitMessage(changeset.getDescription()));
|
List<TrailerPersonDto> collectedTrailers = new ArrayList<>();
|
||||||
|
changesetTrailersSet.forEach(changesetTrailers -> collectedTrailers.addAll(changesetTrailers.getTrailers(repository, changeset)));
|
||||||
|
target.setTrailerPersons(collectedTrailers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
void removeTrailerFromChangesetDescription(@MappingTarget ChangesetDto target) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
try (Scanner scanner = new Scanner(target.getDescription())) {
|
||||||
|
scanner.useDelimiter(Pattern.compile("[\\n]"));
|
||||||
|
while (scanner.hasNext()) {
|
||||||
|
String line = scanner.next();
|
||||||
|
if (!line.contains("-by:")) {
|
||||||
|
builder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target.setDescription(builder.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObjectFactory
|
@ObjectFactory
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ package sonia.scm.api.v2.resources;
|
|||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.servlet.ServletScopes;
|
import com.google.inject.servlet.ServletScopes;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
import sonia.scm.repository.ChangesetTrailerTypes;
|
|
||||||
import sonia.scm.web.api.RepositoryToHalMapper;
|
import sonia.scm.web.api.RepositoryToHalMapper;
|
||||||
|
|
||||||
public class MapperModule extends AbstractModule {
|
public class MapperModule extends AbstractModule {
|
||||||
@@ -78,7 +77,6 @@ public class MapperModule extends AbstractModule {
|
|||||||
bind(MeDtoFactory.class);
|
bind(MeDtoFactory.class);
|
||||||
bind(UIPluginDtoMapper.class);
|
bind(UIPluginDtoMapper.class);
|
||||||
bind(UIPluginDtoCollectionMapper.class);
|
bind(UIPluginDtoCollectionMapper.class);
|
||||||
bind(ChangesetTrailerTypes.class).to(ChangesetTrailerExtractor.TrailerTypes.class);
|
|
||||||
|
|
||||||
bind(ScmPathInfoStore.class).in(ServletScopes.REQUEST);
|
bind(ScmPathInfoStore.class).in(ServletScopes.REQUEST);
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ import sonia.scm.web.security.DefaultAdministrationContext;
|
|||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
class ScmServletModule extends ServletModule {
|
class ScmServletModule extends ServletModule {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import sonia.scm.repository.Branch;
|
|||||||
import sonia.scm.repository.Branches;
|
import sonia.scm.repository.Branches;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
import sonia.scm.repository.ChangesetPagingResult;
|
import sonia.scm.repository.ChangesetPagingResult;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Person;
|
import sonia.scm.repository.Person;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
@@ -61,6 +62,7 @@ import java.net.URI;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -113,6 +115,9 @@ public class BranchRootResourceTest extends RepositoryTestBase {
|
|||||||
@Mock
|
@Mock
|
||||||
private TagCollectionToDtoMapper tagCollectionToDtoMapper;
|
private TagCollectionToDtoMapper tagCollectionToDtoMapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Set<ChangesetTrailers> changesetTrailers;
|
||||||
|
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
||||||
|
|||||||
@@ -24,11 +24,12 @@
|
|||||||
|
|
||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import sonia.scm.api.v2.resources.ChangesetTrailerExtractor.TrailerTypes;
|
import sonia.scm.repository.Changeset;
|
||||||
|
import sonia.scm.repository.Repository;
|
||||||
|
import sonia.scm.repository.RepositoryTestData;
|
||||||
import sonia.scm.user.DisplayUser;
|
import sonia.scm.user.DisplayUser;
|
||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
@@ -37,21 +38,17 @@ import java.util.List;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class ChangesetTrailerExtractorTest {
|
class ChangesetDescriptionTrailersTest {
|
||||||
|
|
||||||
private ChangesetTrailerExtractor extractor;
|
private static final Repository REPOSITORY = RepositoryTestData.createHeartOfGold();
|
||||||
|
|
||||||
@BeforeEach
|
private final ChangesetDescriptionTrailers changesetDescriptionTrailers = new ChangesetDescriptionTrailers();
|
||||||
void initExtractor() {
|
|
||||||
TrailerTypes trailerTypes = new TrailerTypes();
|
|
||||||
extractor = new ChangesetTrailerExtractor(trailerTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnEmptyList() {
|
void shouldReturnEmptyList() {
|
||||||
String commitMessage = "zaphod beetlebrox";
|
Changeset changeset = createChangeset("zaphod beeblebrox");
|
||||||
|
|
||||||
List<TrailerPersonDto> trailerPersons = extractor.extractTrailersFromCommitMessage(commitMessage);
|
List<TrailerPersonDto> trailerPersons = changesetDescriptionTrailers.getTrailers(REPOSITORY, changeset);
|
||||||
|
|
||||||
assertThat(trailerPersons).isNotNull();
|
assertThat(trailerPersons).isNotNull();
|
||||||
assertThat(trailerPersons).isEmpty();
|
assertThat(trailerPersons).isEmpty();
|
||||||
@@ -60,26 +57,26 @@ class ChangesetTrailerExtractorTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldReturnTrailerPersonsWithCoAuthors() {
|
void shouldReturnTrailerPersonsWithCoAuthors() {
|
||||||
DisplayUser displayUser = createDisplayUser("Arthur Dent", "dent@hitchhiker.org");
|
DisplayUser displayUser = createDisplayUser("Arthur Dent", "dent@hitchhiker.org");
|
||||||
String commitMessage = "zaphod beetlebrox\n\nCo-authored-by: Arthur Dent <dent@hitchhiker.org>";
|
Changeset changeset = createChangeset("zaphod beeblebrox\n\nCo-authored-by: Arthur Dent <dent@hitchhiker.org>");
|
||||||
|
|
||||||
PersonDto personDto = createPersonDto(displayUser);
|
PersonDto personDto = createPersonDto(displayUser);
|
||||||
|
|
||||||
List<TrailerPersonDto> trailerPersons = extractor.extractTrailersFromCommitMessage(commitMessage);
|
List<TrailerPersonDto> trailerPersons = changesetDescriptionTrailers.getTrailers(REPOSITORY, changeset);
|
||||||
|
|
||||||
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
TrailerPersonDto trailerPerson = trailerPersons.get(0);
|
||||||
assertThat(trailerPersonDto.getTrailerType()).isEqualTo("Co-authored-by");
|
assertThat(trailerPerson.getTrailerType()).isEqualTo("Co-authored-by");
|
||||||
assertThat(trailerPersonDto.getName()).isEqualTo(personDto.getName());
|
assertThat(trailerPerson.getName()).isEqualTo(personDto.getName());
|
||||||
assertThat(trailerPersonDto.getMail()).isEqualTo(personDto.getMail());
|
assertThat(trailerPerson.getMail()).isEqualTo(personDto.getMail());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnTrailerPersonsWithReviewers() {
|
void shouldReturnTrailerPersonsWithReviewers() {
|
||||||
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
||||||
String commitMessage = "zaphod beetlebrox\nReviewed-by: Tricia McMillan <trillian@hitchhiker.org>";
|
Changeset changeset = createChangeset("zaphod beeblebrox\nReviewed-by: Tricia McMillan <trillian@hitchhiker.org>");
|
||||||
|
|
||||||
PersonDto personDto = createPersonDto(displayUser);
|
PersonDto personDto = createPersonDto(displayUser);
|
||||||
|
|
||||||
List<TrailerPersonDto> trailerPersons = extractor.extractTrailersFromCommitMessage(commitMessage);
|
List<TrailerPersonDto> trailerPersons = changesetDescriptionTrailers.getTrailers(REPOSITORY, changeset);
|
||||||
|
|
||||||
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
||||||
|
|
||||||
@@ -91,11 +88,11 @@ class ChangesetTrailerExtractorTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldReturnTrailerPersonsWithSigner() {
|
void shouldReturnTrailerPersonsWithSigner() {
|
||||||
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
||||||
String commitMessage = "zaphod beetlebrox\nSigned-off-by: Tricia McMillan <trillian@hitchhiker.org>";
|
Changeset changeset = createChangeset("zaphod beeblebrox\nSigned-off-by: Tricia McMillan <trillian@hitchhiker.org>");
|
||||||
|
|
||||||
PersonDto personDto = createPersonDto(displayUser);
|
PersonDto personDto = createPersonDto(displayUser);
|
||||||
|
|
||||||
List<TrailerPersonDto> trailerPersons = extractor.extractTrailersFromCommitMessage(commitMessage);
|
List<TrailerPersonDto> trailerPersons = changesetDescriptionTrailers.getTrailers(REPOSITORY, changeset);
|
||||||
|
|
||||||
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
||||||
|
|
||||||
@@ -107,11 +104,11 @@ class ChangesetTrailerExtractorTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldReturnTrailerPersonsWithCommitter() {
|
void shouldReturnTrailerPersonsWithCommitter() {
|
||||||
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
DisplayUser displayUser = createDisplayUser("Tricia McMillan", "trillian@hitchhiker.org");
|
||||||
String commitMessage = "zaphod beetlebrox\nCommitted-by: Tricia McMillan <trillian@hitchhiker.org>";
|
Changeset changeset = createChangeset("zaphod beeblebrox\nCommitted-by: Tricia McMillan <trillian@hitchhiker.org>");
|
||||||
|
|
||||||
PersonDto personDto = createPersonDto(displayUser);
|
PersonDto personDto = createPersonDto(displayUser);
|
||||||
|
|
||||||
List<TrailerPersonDto> trailerPersons = extractor.extractTrailersFromCommitMessage(commitMessage);
|
List<TrailerPersonDto> trailerPersons = changesetDescriptionTrailers.getTrailers(REPOSITORY, changeset);
|
||||||
|
|
||||||
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
TrailerPersonDto trailerPersonDto = trailerPersons.get(0);
|
||||||
|
|
||||||
@@ -120,9 +117,14 @@ class ChangesetTrailerExtractorTest {
|
|||||||
assertThat(trailerPersonDto.getMail()).isEqualTo(personDto.getMail());
|
assertThat(trailerPersonDto.getMail()).isEqualTo(personDto.getMail());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Changeset createChangeset(String commitMessage) {
|
||||||
|
Changeset changeset = new Changeset();
|
||||||
|
changeset.setDescription(commitMessage);
|
||||||
|
return changeset;
|
||||||
|
}
|
||||||
|
|
||||||
private DisplayUser createDisplayUser(String name, String mail) {
|
private DisplayUser createDisplayUser(String name, String mail) {
|
||||||
DisplayUser displayUser = DisplayUser.from(new User(name, name, mail));
|
return DisplayUser.from(new User(name, name, mail));
|
||||||
return displayUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PersonDto createPersonDto(DisplayUser displayUser) {
|
private PersonDto createPersonDto(DisplayUser displayUser) {
|
||||||
@@ -43,6 +43,7 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
import sonia.scm.repository.ChangesetPagingResult;
|
import sonia.scm.repository.ChangesetPagingResult;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Person;
|
import sonia.scm.repository.Person;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
@@ -56,6 +57,7 @@ import java.net.URI;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -68,7 +70,6 @@ import static org.mockito.Mockito.when;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ChangesetRootResourceTest extends RepositoryTestBase {
|
public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||||
|
|
||||||
|
|
||||||
public static final String CHANGESET_PATH = "space/repo/changesets/";
|
public static final String CHANGESET_PATH = "space/repo/changesets/";
|
||||||
public static final String CHANGESET_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + CHANGESET_PATH;
|
public static final String CHANGESET_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + CHANGESET_PATH;
|
||||||
|
|
||||||
@@ -86,6 +87,10 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
|||||||
@Mock
|
@Mock
|
||||||
private LogCommandBuilder logCommandBuilder;
|
private LogCommandBuilder logCommandBuilder;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Set<ChangesetTrailers> changesetTrailers;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
private ChangesetCollectionToDtoMapper changesetCollectionToDtoMapper;
|
private ChangesetCollectionToDtoMapper changesetCollectionToDtoMapper;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
@@ -93,11 +98,9 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
|||||||
|
|
||||||
private ChangesetRootResource changesetRootResource;
|
private ChangesetRootResource changesetRootResource;
|
||||||
|
|
||||||
|
|
||||||
private final Subject subject = mock(Subject.class);
|
private final Subject subject = mock(Subject.class);
|
||||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void prepareEnvironment() {
|
public void prepareEnvironment() {
|
||||||
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import sonia.scm.ContextEntry;
|
|||||||
import sonia.scm.NotFoundException;
|
import sonia.scm.NotFoundException;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
import sonia.scm.repository.ChangesetPagingResult;
|
import sonia.scm.repository.ChangesetPagingResult;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
import sonia.scm.repository.InternalRepositoryException;
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Person;
|
import sonia.scm.repository.Person;
|
||||||
@@ -59,6 +60,7 @@ import java.net.URISyntaxException;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -89,6 +91,9 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
|||||||
|
|
||||||
private FileHistoryCollectionToDtoMapper fileHistoryCollectionToDtoMapper;
|
private FileHistoryCollectionToDtoMapper fileHistoryCollectionToDtoMapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Set<ChangesetTrailers> changesetTrailers;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||||||
import sonia.scm.NotFoundException;
|
import sonia.scm.NotFoundException;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
import sonia.scm.repository.ChangesetPagingResult;
|
import sonia.scm.repository.ChangesetPagingResult;
|
||||||
|
import sonia.scm.repository.ChangesetTrailers;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Person;
|
import sonia.scm.repository.Person;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
@@ -64,6 +65,7 @@ import java.net.URISyntaxException;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -78,7 +80,6 @@ import static sonia.scm.repository.api.DiffFormat.NATIVE;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class IncomingRootResourceTest extends RepositoryTestBase {
|
public class IncomingRootResourceTest extends RepositoryTestBase {
|
||||||
|
|
||||||
|
|
||||||
public static final String INCOMING_PATH = "space/repo/incoming/";
|
public static final String INCOMING_PATH = "space/repo/incoming/";
|
||||||
public static final String INCOMING_CHANGESETS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
|
public static final String INCOMING_CHANGESETS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
|
||||||
public static final String INCOMING_DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
|
public static final String INCOMING_DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
|
||||||
@@ -108,6 +109,9 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
|
|||||||
|
|
||||||
private IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper;
|
private IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Set<ChangesetTrailers> changesetTrailers;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
private DefaultChangesetToChangesetDtoMapperImpl changesetToChangesetDtoMapper;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user