From 697cab246c78e655541cd467cee8289246b18ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20=C5=BDivkov?= Date: Tue, 29 Apr 2014 16:46:50 +0200 Subject: [PATCH] Add --other-branches option to the /changes//revisions//mergeable When the --other-branches option is specified the mergeability will also be checked for other branches. The response will include a mergeable_into list of branch names where this change merges cleanly. This information may be displayed in the UI and serve as a reminder that a bugfix could be cleanly back-ported into a release branch. Change-Id: I1d7bbd6675607a55a621ea8e2875a8c9ffd19d30 --- Documentation/rest-api-changes.txt | 38 ++++++++-- .../gerrit/server/change/Mergeable.java | 69 ++++++++++++++----- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index 7f6e879e46..f7b09b23bf 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -1793,6 +1793,34 @@ As response a link:#mergeable-info[MergeableInfo] entity is returned. } ---- +If the `other-branches` parameter is specified, the mergeability will also be +checked for all other branches. + +.Request +---- + GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/current/mergeable?other-branches HTTP/1.0 +---- + +The response will then contain a list of all other branches where this changes +could merge cleanly. + +.Response +---- + HTTP/1.1 200 OK + Content-Disposition: attachment + Content-Type: application/json;charset=UTF-8 + + )]}' + { + submit_type: "MERGE_IF_NECESSARY", + mergeable: true, + mergeable_into: [ + "refs/heads/stable-2.7", + "refs/heads/stable-2.8", + ] + } +---- + [[get-submit-type]] === Get Submit Type -- @@ -3115,15 +3143,17 @@ to the value descriptions. The `MergeableInfo` entity contains information about the mergeability of a change. -[options="header",width="50%",cols="1,6"] +[options="header",width="50%",cols="1,^1,5"] |============================ -|Field Name |Description -|`submit_type`| +|Field Name ||Description +|`submit_type` || Submit type used for this change, can be `MERGE_IF_NECESSARY`, `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`, `MERGE_ALWAYS` or `CHERRY_PICK`. -|`mergeable` | +|`mergeable` || `true` if this change is cleanly mergeable, `false` otherwise +|`mergeable_into`|optional| +A list of other branch names where this change could merge cleanly [[restore-input]] === RestoreInput diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java index c00b96c969..e78573671d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java @@ -46,12 +46,15 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.jgit.revwalk.RevWalk; +import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Set; @@ -61,8 +64,13 @@ public class Mergeable implements RestReadView { public static class MergeableInfo { public SubmitType submitType; public boolean mergeable; + public List mergeableInto; } + @Option(name = "--other-branches", aliases = {"-o"}, + usage = "test mergeability for other branches too") + private boolean otherBranches; + private final TestSubmitType.Get submitType; private final GitRepositoryManager gitManager; private final SubmitStrategyFactory submitStrategyFactory; @@ -113,6 +121,18 @@ public class Mergeable implements RestReadView { result.mergeable = refresh(change, ps, result.submitType, git, refs, ref); } + + if (otherBranches) { + result.mergeableInto = new ArrayList<>(); + for (Ref r : refs.values()) { + if (r.getName().startsWith(Constants.R_HEADS) + && !r.getName().equals(ref.getName())) { + if (isMergeable(change, ps, SubmitType.CHERRY_PICK, git, refs, r)) { + result.mergeableInto.add(r.getName()); + } + } + } + } } finally { git.close(); } @@ -136,6 +156,36 @@ public class Mergeable implements RestReadView { Repository git, Map refs, final Ref ref) throws IOException, OrmException { + + final boolean mergeable = isMergeable(change, ps, type, git, refs, ref); + + Change c = db.get().changes().atomicUpdate( + change.getId(), + new AtomicUpdate() { + @Override + public Change update(Change c) { + if (c.getStatus().isOpen() + && ps.getId().equals(c.currentPatchSetId())) { + c.setMergeable(mergeable); + c.setLastSha1MergeTested(toRevId(ref)); + return c; + } else { + return null; + } + } + }); + if (c != null) { + indexer.index(db.get(), c); + } + return mergeable; + } + + private boolean isMergeable(Change change, + final PatchSet ps, + SubmitType type, + Repository git, + Map refs, + final Ref ref) throws IOException, OrmException { RevWalk rw = new RevWalk(git) { @Override protected CodeReviewCommit createCommit(AnyObjectId id) { @@ -176,25 +226,6 @@ public class Mergeable implements RestReadView { accepted, change.getDest()).dryRun(tip, rev); } - - Change c = db.get().changes().atomicUpdate( - change.getId(), - new AtomicUpdate() { - @Override - public Change update(Change c) { - if (c.getStatus().isOpen() - && ps.getId().equals(c.currentPatchSetId())) { - c.setMergeable(mergeable); - c.setLastSha1MergeTested(toRevId(ref)); - return c; - } else { - return null; - } - } - }); - if (c != null) { - indexer.index(db.get(), c); - } return mergeable; } catch (MergeException | IOException | NoSuchProjectException e) { log.error(String.format(