From a1ff55d08432b11763b03315d29f77078c56b078 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Tue, 26 Nov 2019 13:22:00 +0100 Subject: [PATCH 01/19] override global radio stylings and use local styles instead --- scm-ui/ui-components/src/forms/Radio.tsx | 10 ++++++++-- scm-ui/ui-styles/src/scm.scss | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/scm-ui/ui-components/src/forms/Radio.tsx b/scm-ui/ui-components/src/forms/Radio.tsx index 429fc91077..e9aea098c4 100644 --- a/scm-ui/ui-components/src/forms/Radio.tsx +++ b/scm-ui/ui-components/src/forms/Radio.tsx @@ -1,5 +1,11 @@ import React, { ChangeEvent } from "react"; import { Help } from "../index"; +import styled from "styled-components"; + + +const StyledRadio = styled.label` + margin-right: 0.5em; +`; type Props = { label?: string; @@ -33,7 +39,7 @@ class Radio extends React.Component { because jsx label does not the custom disabled attribute but bulma does. // @ts-ignore */} - + ); } diff --git a/scm-ui/ui-styles/src/scm.scss b/scm-ui/ui-styles/src/scm.scss index 01d8d3e55a..82b6b609c3 100644 --- a/scm-ui/ui-styles/src/scm.scss +++ b/scm-ui/ui-styles/src/scm.scss @@ -809,6 +809,12 @@ form .field:not(.is-grouped) { } } +// radio +//overwrite bulma's default margin +.radio + .radio { + margin-left: 0; +} + // cursor .has-cursor-pointer { cursor: pointer; From dc6d9cc5eb8bbbff90a16e12fd231cfaa8f062c8 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 18 Dec 2019 11:03:07 +0100 Subject: [PATCH 02/19] return revision on merge --- .../repository/api/MergeCommandResult.java | 12 +++- .../java/sonia/scm/repository/spi/Differ.java | 70 ++++++++++--------- .../spi/GitFastForwardIfPossible.java | 3 +- .../scm/repository/spi/GitMergeCommit.java | 12 +++- .../scm/repository/spi/GitMergeStrategy.java | 6 +- .../repository/spi/GitMergeWithSquash.java | 9 ++- .../sonia/scm/repository/spi/GitMerger.java | 17 +++++ .../ui-components/src/repos/LoadingDiff.tsx | 12 +++- .../src/repos/changesets/ChangesetDiff.tsx | 2 +- scm-ui/ui-webapp/public/locales/de/repos.json | 2 +- scm-ui/ui-webapp/public/locales/en/repos.json | 2 +- 11 files changed, 97 insertions(+), 50 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java index 53f712cddc..54b57c668f 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java @@ -13,17 +13,19 @@ import static java.util.Collections.unmodifiableCollection; */ public class MergeCommandResult { private final Collection filesWithConflict; + private static String mergeCommitRevision; - private MergeCommandResult(Collection filesWithConflict) { + public MergeCommandResult(Collection filesWithConflict, String mergeCommitRevision) { this.filesWithConflict = filesWithConflict; + this.mergeCommitRevision = mergeCommitRevision; } public static MergeCommandResult success() { - return new MergeCommandResult(emptyList()); + return new MergeCommandResult(emptyList(), mergeCommitRevision); } public static MergeCommandResult failure(Collection filesWithConflict) { - return new MergeCommandResult(new HashSet<>(filesWithConflict)); + return new MergeCommandResult(new HashSet<>(filesWithConflict), ""); } /** @@ -41,4 +43,8 @@ public class MergeCommandResult { public Collection getFilesWithConflict() { return unmodifiableCollection(filesWithConflict); } + + public String getMergeCommitRevision() { + return mergeCommitRevision; + } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java index 0204ca4e3c..fdecac6314 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java @@ -2,6 +2,7 @@ package sonia.scm.repository.spi; import com.google.common.base.Strings; import org.eclipse.jgit.diff.DiffEntry; +import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; @@ -10,6 +11,8 @@ import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.EmptyTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; +import sonia.scm.ContextEntry; +import sonia.scm.NotFoundException; import sonia.scm.repository.GitUtil; import sonia.scm.util.Util; @@ -35,49 +38,48 @@ final class Differ implements AutoCloseable { } private static Differ create(Repository repository, DiffCommandRequest request) throws IOException { - RevWalk walk = new RevWalk(repository); + RevWalk walk = new RevWalk(repository); - ObjectId revision = repository.resolve(request.getRevision()); - RevCommit commit = walk.parseCommit(revision); + ObjectId revision = repository.resolve(request.getRevision()); + if (revision == null) { + throw NotFoundException.notFound(ContextEntry.ContextBuilder.entity("revision not found", request.getRevision())); + } + RevCommit commit; + try { + commit = walk.parseCommit(revision); + } catch (MissingObjectException ex) { + throw NotFoundException.notFound(ContextEntry.ContextBuilder.entity("revision not found", request.getRevision())); + } - walk.markStart(commit); - commit = walk.next(); - TreeWalk treeWalk = new TreeWalk(repository); - treeWalk.reset(); - treeWalk.setRecursive(true); + walk.markStart(commit); + commit = walk.next(); + TreeWalk treeWalk = new TreeWalk(repository); + treeWalk.reset(); + treeWalk.setRecursive(true); - if (Util.isNotEmpty(request.getPath())) - { - treeWalk.setFilter(PathFilter.create(request.getPath())); - } + if (Util.isNotEmpty(request.getPath())) { + treeWalk.setFilter(PathFilter.create(request.getPath())); + } - if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) - { - ObjectId otherRevision = repository.resolve(request.getAncestorChangeset()); - ObjectId ancestorId = GitUtil.computeCommonAncestor(repository, revision, otherRevision); - RevTree tree = walk.parseCommit(ancestorId).getTree(); + if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) { + ObjectId otherRevision = repository.resolve(request.getAncestorChangeset()); + ObjectId ancestorId = GitUtil.computeCommonAncestor(repository, revision, otherRevision); + RevTree tree = walk.parseCommit(ancestorId).getTree(); + treeWalk.addTree(tree); + } else if (commit.getParentCount() > 0) { + RevTree tree = commit.getParent(0).getTree(); + + if (tree != null) { treeWalk.addTree(tree); - } - else if (commit.getParentCount() > 0) - { - RevTree tree = commit.getParent(0).getTree(); - - if (tree != null) - { - treeWalk.addTree(tree); - } - else - { - treeWalk.addTree(new EmptyTreeIterator()); - } - } - else - { + } else { treeWalk.addTree(new EmptyTreeIterator()); } + } else { + treeWalk.addTree(new EmptyTreeIterator()); + } - treeWalk.addTree(commit.getTree()); + treeWalk.addTree(commit.getTree()); return new Differ(commit, walk, treeWalk); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java index 64a20a33cb..ddca0a78b0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java @@ -7,6 +7,7 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; import java.io.IOException; +import java.util.Collections; class GitFastForwardIfPossible extends GitMergeStrategy { @@ -22,7 +23,7 @@ class GitFastForwardIfPossible extends GitMergeStrategy { MergeResult fastForwardResult = mergeWithFastForwardOnlyMode(); if (fastForwardResult.getMergeStatus().isSuccessful()) { push(); - return MergeCommandResult.success(); + return new MergeCommandResult(Collections.emptyList(), ""); } else { return fallbackMerge.run(); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java index 6aa68a0ea8..f527cff900 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java @@ -3,10 +3,17 @@ package sonia.scm.repository.spi; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeResult; +import org.eclipse.jgit.revwalk.RevCommit; +import sonia.scm.ContextEntry; +import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; import java.io.IOException; +import java.util.Collections; +import java.util.Optional; + +import static sonia.scm.repository.spi.GitMerger.evaluateRevisionFromMergeCommit; class GitMergeCommit extends GitMergeStrategy { @@ -21,11 +28,12 @@ class GitMergeCommit extends GitMergeStrategy { MergeResult result = doMergeInClone(mergeCommand); if (result.getMergeStatus().isSuccessful()) { - doCommit(); + Optional revCommit = doCommit(); push(); - return MergeCommandResult.success(); + return new MergeCommandResult(Collections.emptyList(), evaluateRevisionFromMergeCommit(revCommit)); } else { return analyseFailure(result); } } + } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java index 1d53b99c99..17b4571820 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java @@ -6,6 +6,7 @@ import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.revwalk.RevCommit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.repository.InternalRepositoryException; @@ -14,6 +15,7 @@ import sonia.scm.repository.api.MergeCommandResult; import java.io.IOException; import java.text.MessageFormat; +import java.util.Optional; abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker { @@ -52,9 +54,9 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker doCommit() { logger.debug("merged branch {} into {}", toMerge, target); - doCommit(MessageFormat.format(determineMessageTemplate(), toMerge, target), author); + return doCommit(MessageFormat.format(determineMessageTemplate(), toMerge, target), author); } private String determineMessageTemplate() { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java index b688956404..a1e921e8a9 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java @@ -2,11 +2,16 @@ package sonia.scm.repository.spi; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeResult; +import org.eclipse.jgit.revwalk.RevCommit; import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; import org.eclipse.jgit.api.MergeCommand; import java.io.IOException; +import java.util.Collections; +import java.util.Optional; + +import static sonia.scm.repository.spi.GitMerger.evaluateRevisionFromMergeCommit; class GitMergeWithSquash extends GitMergeStrategy { @@ -21,9 +26,9 @@ class GitMergeWithSquash extends GitMergeStrategy { MergeResult result = doMergeInClone(mergeCommand); if (result.getMergeStatus().isSuccessful()) { - doCommit(); + Optional revCommit = doCommit(); push(); - return MergeCommandResult.success(); + return new MergeCommandResult(Collections.emptyList(), evaluateRevisionFromMergeCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java new file mode 100644 index 0000000000..87334e5a57 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java @@ -0,0 +1,17 @@ +package sonia.scm.repository.spi; + +import org.eclipse.jgit.revwalk.RevCommit; +import sonia.scm.ContextEntry; +import sonia.scm.repository.InternalRepositoryException; + +import java.util.Optional; + +public class GitMerger { + + static String evaluateRevisionFromMergeCommit(Optional revCommit) { + if (revCommit.isPresent()) { + return revCommit.get().toString().split(" ")[1]; + } + throw new InternalRepositoryException(ContextEntry.ContextBuilder.entity(GitMergeCommit.class, "merge commit failed"), "could not create commit on merge"); + } +} diff --git a/scm-ui/ui-components/src/repos/LoadingDiff.tsx b/scm-ui/ui-components/src/repos/LoadingDiff.tsx index 45b62f9b35..ec782bc968 100644 --- a/scm-ui/ui-components/src/repos/LoadingDiff.tsx +++ b/scm-ui/ui-components/src/repos/LoadingDiff.tsx @@ -7,8 +7,11 @@ import parser from "gitdiff-parser"; import Loading from "../Loading"; import Diff from "./Diff"; import { DiffObjectProps, File } from "./DiffTypes"; +import { NotFoundError } from "../errors"; +import { Notification } from "../index"; +import {withTranslation, WithTranslation} from "react-i18next"; -type Props = DiffObjectProps & { +type Props = WithTranslation & DiffObjectProps & { url: string; defaultCollapse?: boolean; }; @@ -43,7 +46,7 @@ class LoadingDiff extends React.Component { fetchDiff = () => { const { url } = this.props; - this.setState({loading: true}); + this.setState({ loading: true }); apiClient .get(url) .then(response => response.text()) @@ -66,6 +69,9 @@ class LoadingDiff extends React.Component { render() { const { diff, loading, error } = this.state; if (error) { + if (error instanceof NotFoundError) { + return {this.props.t("changesets.noChangesets")}; + } return ; } else if (loading) { return ; @@ -77,4 +83,4 @@ class LoadingDiff extends React.Component { } } -export default LoadingDiff; +export default withTranslation("repos")(LoadingDiff); diff --git a/scm-ui/ui-components/src/repos/changesets/ChangesetDiff.tsx b/scm-ui/ui-components/src/repos/changesets/ChangesetDiff.tsx index 78f4e90cb3..1789cb5517 100644 --- a/scm-ui/ui-components/src/repos/changesets/ChangesetDiff.tsx +++ b/scm-ui/ui-components/src/repos/changesets/ChangesetDiff.tsx @@ -28,7 +28,7 @@ class ChangesetDiff extends React.Component { return {t("changeset.diffNotSupported")}; } else { const url = this.createUrl(changeset); - return ; + return ; } } } diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json index df6c534ece..83a7918018 100644 --- a/scm-ui/ui-webapp/public/locales/de/repos.json +++ b/scm-ui/ui-webapp/public/locales/de/repos.json @@ -72,7 +72,7 @@ "changesets": { "errorTitle": "Fehler", "errorSubtitle": "Changesets konnten nicht abgerufen werden", - "noChangesets": "Keine Changesets in diesem Branch gefunden.", + "noChangesets": "Keine Changesets in diesem Branch gefunden. Die Commits könnten gelöscht wurden sein.", "branchSelectorLabel": "Branches", "collapseDiffs": "Auf-/Zuklappen" }, diff --git a/scm-ui/ui-webapp/public/locales/en/repos.json b/scm-ui/ui-webapp/public/locales/en/repos.json index 103e30b825..eaeba49e16 100644 --- a/scm-ui/ui-webapp/public/locales/en/repos.json +++ b/scm-ui/ui-webapp/public/locales/en/repos.json @@ -72,7 +72,7 @@ "changesets": { "errorTitle": "Error", "errorSubtitle": "Could not fetch changesets", - "noChangesets": "No changesets found for this branch.", + "noChangesets": "No changesets found for this branch. The commits could have been removed.", "branchSelectorLabel": "Branches", "collapseDiffs": "Collapse" }, From 83cc1c4a6ff2a71eb207509649da6efed5d57532 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 18 Dec 2019 13:17:30 +0100 Subject: [PATCH 03/19] return revision on merge --- .../repository/api/MergeCommandResult.java | 22 +++++++------------ .../spi/GitFastForwardIfPossible.java | 2 +- .../scm/repository/spi/GitMergeStrategy.java | 2 +- .../repository/spi/GitMergeWithSquash.java | 4 ++-- .../sonia/scm/repository/spi/GitMerger.java | 3 ++- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java index 54b57c668f..5680416925 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java @@ -1,9 +1,7 @@ package sonia.scm.repository.api; import java.util.Collection; -import java.util.HashSet; -import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableCollection; /** @@ -13,19 +11,15 @@ import static java.util.Collections.unmodifiableCollection; */ public class MergeCommandResult { private final Collection filesWithConflict; - private static String mergeCommitRevision; + private String newHeadRevision; - public MergeCommandResult(Collection filesWithConflict, String mergeCommitRevision) { + public MergeCommandResult(Collection filesWithConflict) { this.filesWithConflict = filesWithConflict; - this.mergeCommitRevision = mergeCommitRevision; } - public static MergeCommandResult success() { - return new MergeCommandResult(emptyList(), mergeCommitRevision); - } - - public static MergeCommandResult failure(Collection filesWithConflict) { - return new MergeCommandResult(new HashSet<>(filesWithConflict), ""); + public MergeCommandResult(Collection filesWithConflict, String newHeadRevision) { + this.filesWithConflict = filesWithConflict; + this.newHeadRevision = newHeadRevision; } /** @@ -33,7 +27,7 @@ public class MergeCommandResult { * merge conflicts. In this case you can use {@link #getFilesWithConflict()} to check what files could not be merged. */ public boolean isSuccess() { - return filesWithConflict.isEmpty(); + return filesWithConflict.isEmpty() && newHeadRevision != null; } /** @@ -44,7 +38,7 @@ public class MergeCommandResult { return unmodifiableCollection(filesWithConflict); } - public String getMergeCommitRevision() { - return mergeCommitRevision; + public String getNewHeadRevision() { + return newHeadRevision; } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java index ddca0a78b0..cf03e832a3 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java @@ -23,7 +23,7 @@ class GitFastForwardIfPossible extends GitMergeStrategy { MergeResult fastForwardResult = mergeWithFastForwardOnlyMode(); if (fastForwardResult.getMergeStatus().isSuccessful()) { push(); - return new MergeCommandResult(Collections.emptyList(), ""); + return new MergeCommandResult(Collections.emptyList(), fastForwardResult.getNewHead().toString()); } else { return fallbackMerge.run(); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java index 17b4571820..16048c1ef6 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java @@ -69,6 +69,6 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker Date: Wed, 18 Dec 2019 14:33:50 +0100 Subject: [PATCH 04/19] fix unit test --- .../src/main/java/sonia/scm/repository/spi/GitMerger.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java index 6fe942ed7e..5bca7440d2 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java @@ -1,9 +1,6 @@ package sonia.scm.repository.spi; -import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.revwalk.RevCommit; -import sonia.scm.ContextEntry; -import sonia.scm.repository.InternalRepositoryException; import java.util.Optional; @@ -13,6 +10,6 @@ public class GitMerger { if (revCommit.isPresent()) { return revCommit.get().toString().split(" ")[1]; } - throw new InternalRepositoryException(ContextEntry.ContextBuilder.entity(GitMerger.class, "merge commit failed"), "could not create commit on merge"); + return ""; } } From c5f73931165394bff068e73d73030f9c6a7487a0 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 18 Dec 2019 14:38:09 +0100 Subject: [PATCH 05/19] rename helper class --- .../main/java/sonia/scm/repository/spi/GitMergeCommit.java | 6 ++---- .../java/sonia/scm/repository/spi/GitMergeWithSquash.java | 4 ++-- .../spi/{GitMerger.java => GitRevisionExtractor.java} | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) rename scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/{GitMerger.java => GitRevisionExtractor.java} (66%) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java index f527cff900..3c76ae1631 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java @@ -4,8 +4,6 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.revwalk.RevCommit; -import sonia.scm.ContextEntry; -import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; @@ -13,7 +11,7 @@ import java.io.IOException; import java.util.Collections; import java.util.Optional; -import static sonia.scm.repository.spi.GitMerger.evaluateRevisionFromMergeCommit; +import static sonia.scm.repository.spi.GitRevisionExtractor.extractRevisionFromRevCommit; class GitMergeCommit extends GitMergeStrategy { @@ -30,7 +28,7 @@ class GitMergeCommit extends GitMergeStrategy { if (result.getMergeStatus().isSuccessful()) { Optional revCommit = doCommit(); push(); - return new MergeCommandResult(Collections.emptyList(), evaluateRevisionFromMergeCommit(revCommit)); + return new MergeCommandResult(Collections.emptyList(), extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java index d50ff1737d..44a690cbd0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java @@ -11,7 +11,7 @@ import java.io.IOException; import java.util.Collections; import java.util.Optional; -import static sonia.scm.repository.spi.GitMerger.evaluateRevisionFromMergeCommit; +import static sonia.scm.repository.spi.GitRevisionExtractor.extractRevisionFromRevCommit; class GitMergeWithSquash extends GitMergeStrategy { @@ -28,7 +28,7 @@ class GitMergeWithSquash extends GitMergeStrategy { if (result.getMergeStatus().isSuccessful()) { Optional revCommit = doCommit(); push(); - return new MergeCommandResult(Collections.emptyList(), evaluateRevisionFromMergeCommit(revCommit)); + return new MergeCommandResult(Collections.emptyList(), extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java similarity index 66% rename from scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java rename to scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java index 5bca7440d2..6db9dea066 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMerger.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java @@ -4,9 +4,9 @@ import org.eclipse.jgit.revwalk.RevCommit; import java.util.Optional; -public class GitMerger { +public class GitRevisionExtractor { - static String evaluateRevisionFromMergeCommit(Optional revCommit) { + static String extractRevisionFromRevCommit(Optional revCommit) { if (revCommit.isPresent()) { return revCommit.get().toString().split(" ")[1]; } From ba6f8e5b4add69ef6c47d2a329503031d908b49b Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 18 Dec 2019 16:04:16 +0100 Subject: [PATCH 06/19] Small typo --- scm-ui/ui-webapp/public/locales/de/repos.json | 2 +- scm-ui/ui-webapp/public/locales/es/repos.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json index 83a7918018..3ed9804fe3 100644 --- a/scm-ui/ui-webapp/public/locales/de/repos.json +++ b/scm-ui/ui-webapp/public/locales/de/repos.json @@ -72,7 +72,7 @@ "changesets": { "errorTitle": "Fehler", "errorSubtitle": "Changesets konnten nicht abgerufen werden", - "noChangesets": "Keine Changesets in diesem Branch gefunden. Die Commits könnten gelöscht wurden sein.", + "noChangesets": "Keine Changesets in diesem Branch gefunden. Die Commits könnten gelöscht worden sein.", "branchSelectorLabel": "Branches", "collapseDiffs": "Auf-/Zuklappen" }, diff --git a/scm-ui/ui-webapp/public/locales/es/repos.json b/scm-ui/ui-webapp/public/locales/es/repos.json index 3b2451cceb..4e18669287 100644 --- a/scm-ui/ui-webapp/public/locales/es/repos.json +++ b/scm-ui/ui-webapp/public/locales/es/repos.json @@ -72,7 +72,7 @@ "changesets": { "errorTitle": "Error", "errorSubtitle": "No se han podido recuperar los changesets", - "noChangesets": "No se han encontrado changesets para esta rama branch.", + "noChangesets": "No se han encontrado changesets para esta rama branch. Los commits podrían haber sido eliminados.", "branchSelectorLabel": "Ramas", "collapseDiffs": "Colapso" }, From 39b4c59d82614726644fd60fd439e245de7db07b Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Thu, 19 Dec 2019 08:25:28 +0100 Subject: [PATCH 07/19] add unit tests --- .../spi/GitRevisionExtractorTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java new file mode 100644 index 0000000000..514d777f2a --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java @@ -0,0 +1,30 @@ +package sonia.scm.repository.spi; + +import org.eclipse.jgit.revwalk.RevCommit; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class GitRevisionExtractorTest { + + @Test + void shouldReturnRevisionFromRevCommit() { + RevCommit revCommit = mock(RevCommit.class); + Optional optionalRevCommit = Optional.of(revCommit); + when(revCommit.toString()).thenReturn("commit 123456abcdef -t 4561"); + String revision = GitRevisionExtractor.extractRevisionFromRevCommit(optionalRevCommit); + assertThat(revision).isEqualTo("123456abcdef"); + } + + @Test + void shouldReturnEmptyStringIfRevCommitNotAvailable() { + Optional optionalRevCommit = Optional.empty(); + String revision = GitRevisionExtractor.extractRevisionFromRevCommit(optionalRevCommit); + assertThat(revision).isEqualTo(""); + } + +} From 1d3e51ce7b911edde833981034809b55e9db8e82 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Thu, 19 Dec 2019 09:27:18 +0100 Subject: [PATCH 08/19] Use static create methods instead of ambiguous constructor --- .../repository/api/MergeCommandResult.java | 19 +++++++++++++------ .../spi/GitFastForwardIfPossible.java | 2 +- .../scm/repository/spi/GitMergeCommit.java | 2 +- .../scm/repository/spi/GitMergeStrategy.java | 2 +- .../repository/spi/GitMergeWithSquash.java | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java index 5680416925..6a8fd8ab0d 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java @@ -1,7 +1,9 @@ package sonia.scm.repository.api; import java.util.Collection; +import java.util.HashSet; +import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableCollection; /** @@ -10,18 +12,23 @@ import static java.util.Collections.unmodifiableCollection; * case you can use {@link #getFilesWithConflict()} to get a list of files with merge conflicts. */ public class MergeCommandResult { + private final Collection filesWithConflict; - private String newHeadRevision; + private final String newHeadRevision; - public MergeCommandResult(Collection filesWithConflict) { - this.filesWithConflict = filesWithConflict; - } - - public MergeCommandResult(Collection filesWithConflict, String newHeadRevision) { + private MergeCommandResult(Collection filesWithConflict, String newHeadRevision) { this.filesWithConflict = filesWithConflict; this.newHeadRevision = newHeadRevision; } + public static MergeCommandResult success(String newHeadRevision) { + return new MergeCommandResult(emptyList(), newHeadRevision); + } + + public static MergeCommandResult failure(Collection filesWithConflict) { + return new MergeCommandResult(new HashSet<>(filesWithConflict), null); + } + /** * If this returns true, the merge was successfull. If this returns false there were * merge conflicts. In this case you can use {@link #getFilesWithConflict()} to check what files could not be merged. diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java index cf03e832a3..85ba8c2f71 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java @@ -23,7 +23,7 @@ class GitFastForwardIfPossible extends GitMergeStrategy { MergeResult fastForwardResult = mergeWithFastForwardOnlyMode(); if (fastForwardResult.getMergeStatus().isSuccessful()) { push(); - return new MergeCommandResult(Collections.emptyList(), fastForwardResult.getNewHead().toString()); + return MergeCommandResult.success(fastForwardResult.getNewHead().toString()); } else { return fallbackMerge.run(); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java index 3c76ae1631..29e404db41 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java @@ -28,7 +28,7 @@ class GitMergeCommit extends GitMergeStrategy { if (result.getMergeStatus().isSuccessful()) { Optional revCommit = doCommit(); push(); - return new MergeCommandResult(Collections.emptyList(), extractRevisionFromRevCommit(revCommit)); + return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java index 16048c1ef6..17b4571820 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java @@ -69,6 +69,6 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker revCommit = doCommit(); push(); - return new MergeCommandResult(Collections.emptyList(), extractRevisionFromRevCommit(revCommit)); + return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } From f7c4894fb2c428fe40f63c58f5bccffef8641213 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Thu, 19 Dec 2019 09:47:31 +0100 Subject: [PATCH 09/19] Let merges without effect throw an exception --- .../java/sonia/scm/repository/spi/MergeCommand.java | 6 ++++++ .../scm/repository/spi/AbstractGitCommand.java | 4 ++++ .../sonia/scm/repository/spi/GitMergeCommit.java | 3 ++- .../scm/repository/spi/GitMergeWithSquash.java | 3 ++- .../scm/repository/spi/GitRevisionExtractor.java | 7 ++----- .../scm/repository/spi/GitMergeCommandTest.java | 13 ++++--------- .../repository/spi/GitRevisionExtractorTest.java | 11 +---------- 7 files changed, 21 insertions(+), 26 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommand.java index a62e373dca..79d6b12c25 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommand.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommand.java @@ -7,6 +7,12 @@ import sonia.scm.repository.api.MergeStrategy; import java.util.Set; public interface MergeCommand { + /** + * Executes the merge. + * @param request The parameters specifying the merge. + * @return Result holding either the new revision or a list of conflicting files. + * @throws sonia.scm.NoChangesMadeException If the merge neither had a conflict nor made any change. + */ MergeCommandResult merge(MergeCommandRequest request); MergeDryRunCommandResult dryRun(MergeCommandRequest request); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index adf7878221..1c807c6fc7 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -186,6 +186,10 @@ class AbstractGitCommand return context; } + sonia.scm.repository.Repository getRepository() { + return repository; + } + void checkOutBranch(String branchName) throws IOException { try { clone.checkout().setName(branchName).call(); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java index 29e404db41..12bbe5f5b1 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java @@ -4,6 +4,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.revwalk.RevCommit; +import sonia.scm.NoChangesMadeException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; @@ -26,7 +27,7 @@ class GitMergeCommit extends GitMergeStrategy { MergeResult result = doMergeInClone(mergeCommand); if (result.getMergeStatus().isSuccessful()) { - Optional revCommit = doCommit(); + RevCommit revCommit = doCommit().orElseThrow(() -> new NoChangesMadeException(getRepository())); push(); return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); } else { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java index e9d48dee3a..2a04e32c64 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeWithSquash.java @@ -4,6 +4,7 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.MergeCommand; import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.revwalk.RevCommit; +import sonia.scm.NoChangesMadeException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.MergeCommandResult; @@ -26,7 +27,7 @@ class GitMergeWithSquash extends GitMergeStrategy { MergeResult result = doMergeInClone(mergeCommand); if (result.getMergeStatus().isSuccessful()) { - Optional revCommit = doCommit(); + RevCommit revCommit = doCommit().orElseThrow(() -> new NoChangesMadeException(getRepository())); push(); return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); } else { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java index 6db9dea066..5055024151 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRevisionExtractor.java @@ -6,10 +6,7 @@ import java.util.Optional; public class GitRevisionExtractor { - static String extractRevisionFromRevCommit(Optional revCommit) { - if (revCommit.isPresent()) { - return revCommit.get().toString().split(" ")[1]; - } - return ""; + static String extractRevisionFromRevCommit(RevCommit revCommit) { + return revCommit.toString().split(" ")[1]; } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java index fcd721c3a2..7ed9c1cb75 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java @@ -12,6 +12,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Rule; import org.junit.Test; +import sonia.scm.NoChangesMadeException; import sonia.scm.NotFoundException; import sonia.scm.repository.Person; import sonia.scm.repository.api.MergeCommandResult; @@ -106,7 +107,7 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { assertThat(mergeCommit.getParent(1).name()).isEqualTo("d81ad6c63d7e2162308d69637b339dedd1d9201c"); } - @Test + @Test(expected = NoChangesMadeException.class) public void shouldNotMergeTwice() throws IOException, GitAPIException { GitMergeCommand command = createCommand(); MergeCommandRequest request = new MergeCommandRequest(); @@ -120,15 +121,9 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { assertThat(mergeCommandResult.isSuccess()).isTrue(); Repository repository = createContext().open(); - ObjectId firstMergeCommit = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call().iterator().next().getId(); + new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call().iterator().next().getId(); - MergeCommandResult secondMergeCommandResult = command.merge(request); - - assertThat(secondMergeCommandResult.isSuccess()).isTrue(); - - ObjectId secondMergeCommit = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call().iterator().next().getId(); - - assertThat(secondMergeCommit).isEqualTo(firstMergeCommit); + command.merge(request); } @Test diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java index 514d777f2a..52a609b6cd 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitRevisionExtractorTest.java @@ -14,17 +14,8 @@ public class GitRevisionExtractorTest { @Test void shouldReturnRevisionFromRevCommit() { RevCommit revCommit = mock(RevCommit.class); - Optional optionalRevCommit = Optional.of(revCommit); when(revCommit.toString()).thenReturn("commit 123456abcdef -t 4561"); - String revision = GitRevisionExtractor.extractRevisionFromRevCommit(optionalRevCommit); + String revision = GitRevisionExtractor.extractRevisionFromRevCommit(revCommit); assertThat(revision).isEqualTo("123456abcdef"); } - - @Test - void shouldReturnEmptyStringIfRevCommitNotAvailable() { - Optional optionalRevCommit = Optional.empty(); - String revision = GitRevisionExtractor.extractRevisionFromRevCommit(optionalRevCommit); - assertThat(revision).isEqualTo(""); - } - } From 60f5c9a9bfc4c7317c2e7f556a66c2b112e38fa2 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 19 Dec 2019 09:08:41 +0000 Subject: [PATCH 10/19] Close branch bugfix/remove_global_styles_radio_button From ded08d6a1dab57c50e5f9f65cf8b8e3df9c05527 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 19 Dec 2019 10:23:16 +0100 Subject: [PATCH 11/19] supress false positive javasecurity:S2083 on CopyOnWrite --- .../src/main/java/sonia/scm/store/CopyOnWrite.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/CopyOnWrite.java b/scm-dao-xml/src/main/java/sonia/scm/store/CopyOnWrite.java index 135221ea82..e4334d42b1 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/CopyOnWrite.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/CopyOnWrite.java @@ -8,6 +8,14 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.UUID; +/** + * CopyOnWrite creates a copy of the target file, before it is modified. This should prevent empty or incomplete files + * on errors such as full disk. + * + * javasecurity:S2083: SonarQube thinks that the path (targetFile) is generated from an http header (HttpUtil), but + * this is not true. It looks like a false-positive, so we suppress the warning for now. + */ +@SuppressWarnings("javasecurity:S2083") public final class CopyOnWrite { private static final Logger LOG = LoggerFactory.getLogger(CopyOnWrite.class); From 148095ad4c1c2a5a613468e0c6baffbf5adfb897 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Thu, 19 Dec 2019 10:30:02 +0100 Subject: [PATCH 12/19] Add revisions of merged branches before merge --- .../repository/api/MergeCommandResult.java | 32 +++++++++++--- .../spi/GitFastForwardIfPossible.java | 2 +- .../scm/repository/spi/GitMergeCommit.java | 2 +- .../scm/repository/spi/GitMergeStrategy.java | 42 ++++++++++++++----- .../repository/spi/GitMergeWithSquash.java | 4 +- .../repository/spi/GitMergeCommandTest.java | 7 ++++ 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java index 6a8fd8ab0d..1e6d5c6447 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandResult.java @@ -15,18 +15,22 @@ public class MergeCommandResult { private final Collection filesWithConflict; private final String newHeadRevision; + private final String targetRevision; + private final String revisionToMerge; - private MergeCommandResult(Collection filesWithConflict, String newHeadRevision) { + private MergeCommandResult(Collection filesWithConflict, String targetRevision, String revisionToMerge, String newHeadRevision) { this.filesWithConflict = filesWithConflict; + this.targetRevision = targetRevision; + this.revisionToMerge = revisionToMerge; this.newHeadRevision = newHeadRevision; } - public static MergeCommandResult success(String newHeadRevision) { - return new MergeCommandResult(emptyList(), newHeadRevision); + public static MergeCommandResult success(String targetRevision, String revisionToMerge, String newHeadRevision) { + return new MergeCommandResult(emptyList(), targetRevision, revisionToMerge, newHeadRevision); } - public static MergeCommandResult failure(Collection filesWithConflict) { - return new MergeCommandResult(new HashSet<>(filesWithConflict), null); + public static MergeCommandResult failure(String targetRevision, String revisionToMerge, Collection filesWithConflict) { + return new MergeCommandResult(new HashSet<>(filesWithConflict), targetRevision, revisionToMerge, null); } /** @@ -45,7 +49,25 @@ public class MergeCommandResult { return unmodifiableCollection(filesWithConflict); } + /** + * Returns the revision of the new head of the target branch, if the merge was successful ({@link #isSuccess()}) + */ public String getNewHeadRevision() { return newHeadRevision; } + + /** + * Returns the revision of the target branch prior to the merge. + */ + public String getTargetRevision() { + return targetRevision; + } + + /** + * Returns the revision of the branch that was merged into the target (or in case of a conflict of the revision that + * should have been merged). + */ + public String getRevisionToMerge() { + return revisionToMerge; + } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java index 85ba8c2f71..84ea1a0bbc 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitFastForwardIfPossible.java @@ -23,7 +23,7 @@ class GitFastForwardIfPossible extends GitMergeStrategy { MergeResult fastForwardResult = mergeWithFastForwardOnlyMode(); if (fastForwardResult.getMergeStatus().isSuccessful()) { push(); - return MergeCommandResult.success(fastForwardResult.getNewHead().toString()); + return createSuccessResult(fastForwardResult.getNewHead().name()); } else { return fallbackMerge.run(); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java index 12bbe5f5b1..9a7d290d3a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommit.java @@ -29,7 +29,7 @@ class GitMergeCommit extends GitMergeStrategy { if (result.getMergeStatus().isSuccessful()) { RevCommit revCommit = doCommit().orElseThrow(() -> new NoChangesMadeException(getRepository())); push(); - return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); + return createSuccessResult(extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java index 17b4571820..8e9f79d1b9 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeStrategy.java @@ -26,37 +26,57 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker doCommit() { - logger.debug("merged branch {} into {}", toMerge, target); - return doCommit(MessageFormat.format(determineMessageTemplate(), toMerge, target), author); + logger.debug("merged branch {} into {}", branchToMerge, targetBranch); + return doCommit(MessageFormat.format(determineMessageTemplate(), branchToMerge, targetBranch), author); + } + + MergeCommandResult createSuccessResult(String newRevision) { + return MergeCommandResult.success(targetRevision.name(), revisionToMerge.name(), newRevision); + } + + ObjectId getTargetRevision() { + return targetRevision; + } + + ObjectId getRevisionToMerge() { + return revisionToMerge; } private String determineMessageTemplate() { @@ -68,7 +88,7 @@ abstract class GitMergeStrategy extends AbstractGitCommand.GitCloneWorker new NoChangesMadeException(getRepository())); push(); - return MergeCommandResult.success(extractRevisionFromRevCommit(revCommit)); + return MergeCommandResult.success(getTargetRevision().name(), revCommit.name(), extractRevisionFromRevCommit(revCommit)); } else { return analyseFailure(result); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java index 7ed9c1cb75..2616d5b6e5 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java @@ -71,6 +71,8 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { MergeCommandResult mergeCommandResult = command.merge(request); assertThat(mergeCommandResult.isSuccess()).isTrue(); + assertThat(mergeCommandResult.getRevisionToMerge()).isEqualTo("91b99de908fcd04772798a31c308a64aea1a5523"); + assertThat(mergeCommandResult.getTargetRevision()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec"); Repository repository = createContext().open(); Iterable commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call(); @@ -229,6 +231,8 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { Repository repository = createContext().open(); assertThat(mergeCommandResult.isSuccess()).isTrue(); + assertThat(mergeCommandResult.getRevisionToMerge()).isEqualTo(mergeCommandResult.getNewHeadRevision()); + assertThat(mergeCommandResult.getTargetRevision()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec"); Iterable commits = new Git(repository).log().add(repository.resolve("master")).setMaxCount(1).call(); RevCommit mergeCommit = commits.iterator().next(); @@ -279,6 +283,9 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { request.setAuthor(new Person("Dirk Gently", "dirk@holistic.det")); MergeCommandResult mergeCommandResult = command.merge(request); + assertThat(mergeCommandResult.getNewHeadRevision()).isEqualTo("35597e9e98fe53167266583848bfef985c2adb27"); + assertThat(mergeCommandResult.getRevisionToMerge()).isEqualTo("35597e9e98fe53167266583848bfef985c2adb27"); + assertThat(mergeCommandResult.getTargetRevision()).isEqualTo("fcd0ef1831e4002ac43ea539f4094334c79ea9ec"); assertThat(mergeCommandResult.isSuccess()).isTrue(); From be6c3879bb1839bd912d2226e188b87dda103780 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Thu, 19 Dec 2019 10:30:21 +0100 Subject: [PATCH 13/19] update storyshots --- .../src/__snapshots__/storyshots.test.ts.snap | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index 25e78abbd8..7fa1b1193f 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -336,7 +336,7 @@ exports[`Storyshots DateFromNow Default 1`] = ` exports[`Storyshots Forms|Checkbox Default 1`] = `