From 944b838d88f727f08d9a199201a1006854ca8a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20=C5=BDivkov?= Date: Thu, 8 May 2014 14:02:15 +0200 Subject: [PATCH] Make the --other-branches configurable Introduce a branchOrder section in the project.config in order to define a branch order and automate the back/forward porting of changes. For now assume only one branchOrder section. For example: [branchOrder] branch = master branch = stable-2.9 branch = stable-2.8 branch = stable-2.7 This format makes the ordering obvious (top-down) and complete: for any two branches from the list the order is defined. The --other-branches will rely on the branchOrder section in order to find out a set of branches for which to check mergeability. With the above example, If a change is pushed to the master branch then the --other-branches option will test mergeability into the stable-2.9, stable-2.8 and stable-2.7 branches. If the changed would be pushed to the stable-2.8 then the --other-branches option would test mergeability only into the stable-2.7 branch. Change-Id: Ib806d7e4b5702fa2d8effd197829b729cad95432 --- Documentation/config-project-config.txt | 35 +++++++++++ .../gerrit/server/change/Mergeable.java | 21 +++++-- .../gerrit/server/git/BranchOrderSection.java | 60 +++++++++++++++++++ .../gerrit/server/git/ProjectConfig.java | 16 +++++ .../gerrit/server/project/ProjectState.java | 11 ++++ 5 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt index 474893db4b..43ede06f9a 100644 --- a/Documentation/config-project-config.txt +++ b/Documentation/config-project-config.txt @@ -198,6 +198,41 @@ link:access-control.html#global_capabilities[Global Capabilities] documentation for a full list of available capabilities. +[[branchOrder-section]] +=== branchOrder section + +Defines a branch ordering which is used for backporting of changes. +Backporting will be offered for a change (in the Gerrit UI) for all +more stable branches where the change can merge cleanly. + +[[branchOrder.branch]]branchOrder.branch:: ++ +A branch name, typically multiple values will be defined. The order of branch +names in this section defines the branch order. The topmost is considered to be +the least stable branch (typically the master branch) and the last one the +most stable (typically the last maintained release branch). + +Example: + +---- +[branchOrder] + branch = master + branch = stable-2.9 + branch = stable-2.8 + branch = stable-2.7 +---- + +The `branchOrder` section is inheritable. This is useful when multiple or all +projects follow the same branch rules. A `branchOrder` section in a child +project completely overrides any `branchOrder` section from a parent i.e. there +is no merging of `branchOrder` sections. A present but empty `branchOrder` +section removes all inherited branch order. + +Branches not listed in this section will not be included in the mergeability +check. If the `branchOrder` section is not defined then the mergeability of a +change into other branches will not be done. + + [[file-groups]] == The file +groups+ 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 e78573671d..f2c4adc61e 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 @@ -24,12 +24,14 @@ import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.RevId; import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.git.BranchOrderSection; import com.google.gerrit.server.git.CodeReviewCommit; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.MergeException; import com.google.gerrit.server.git.strategy.SubmitStrategyFactory; import com.google.gerrit.server.index.ChangeIndexer; import com.google.gerrit.server.project.NoSuchProjectException; +import com.google.gerrit.server.project.ProjectCache; import com.google.gwtorm.server.AtomicUpdate; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; @@ -73,6 +75,7 @@ public class Mergeable implements RestReadView { private final TestSubmitType.Get submitType; private final GitRepositoryManager gitManager; + private final ProjectCache projectCache; private final SubmitStrategyFactory submitStrategyFactory; private final Provider db; private final ChangeIndexer indexer; @@ -82,11 +85,13 @@ public class Mergeable implements RestReadView { @Inject Mergeable(TestSubmitType.Get submitType, GitRepositoryManager gitManager, + ProjectCache projectCache, SubmitStrategyFactory submitStrategyFactory, Provider db, ChangeIndexer indexer) { this.submitType = submitType; this.gitManager = gitManager; + this.projectCache = projectCache; this.submitStrategyFactory = submitStrategyFactory; this.db = db; this.indexer = indexer; @@ -124,11 +129,17 @@ public class Mergeable implements RestReadView { 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()); + BranchOrderSection branchOrder = + projectCache.get(change.getProject()).getBranchOrderSection(); + if (branchOrder != null) { + int prefixLen = Constants.R_HEADS.length(); + for (String n : branchOrder.getMoreStable(ref.getName())) { + Ref other = refs.get(n); + if (other == null) { + continue; + } + if (isMergeable(change, ps, SubmitType.CHERRY_PICK, git, refs, other)) { + result.mergeableInto.add(other.getName().substring(prefixLen)); } } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java new file mode 100644 index 0000000000..c447d31ee4 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BranchOrderSection.java @@ -0,0 +1,60 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.git; + +import com.google.common.collect.ImmutableList; + +import org.eclipse.jgit.lib.Constants; + +import java.util.List; + +public class BranchOrderSection { + + /** + * Branch names ordered from least to the most stable. + * + * Typically the order will be like: master, stable-M.N, stable-M.N-1, ... + */ + private final ImmutableList order; + + public BranchOrderSection(String[] order) { + if (order.length == 0) { + this.order = ImmutableList.of(); + } else { + ImmutableList.Builder builder = ImmutableList.builder(); + for (String b : order) { + builder.add(fullName(b)); + } + this.order = builder.build(); + } + } + + private static String fullName(String branch) { + if (branch.startsWith(Constants.R_HEADS)) { + return branch; + } else { + return Constants.R_HEADS + branch; + } + } + + public List getMoreStable(String branch) { + int i = order.indexOf(fullName(branch)); + if (0 <= i) { + return order.subList(i + 1, order.size()); + } else { + return ImmutableList.of(); + } + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java index d5dae8e44e..c4c1b7fbd4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java @@ -95,6 +95,9 @@ public class ProjectConfig extends VersionedMetaData { private static final String ACCOUNTS = "accounts"; private static final String KEY_SAME_GROUP_VISIBILITY = "sameGroupVisibility"; + private static final String BRANCH_ORDER = "branchOrder"; + private static final String BRANCH = "branch"; + private static final String CONTRIBUTOR_AGREEMENT = "contributor-agreement"; private static final String KEY_ACCEPTED = "accepted"; private static final String KEY_REQUIRE_CONTACT_INFORMATION = "requireContactInformation"; @@ -152,6 +155,7 @@ public class ProjectConfig extends VersionedMetaData { private AccountsSection accountsSection; private Map groupsByUUID; private Map accessSections; + private BranchOrderSection branchOrderSection; private Map contributorAgreements; private Map notifySections; private Map labelSections; @@ -242,6 +246,10 @@ public class ProjectConfig extends VersionedMetaData { return sort(accessSections.values()); } + public BranchOrderSection getBranchOrderSection() { + return branchOrderSection; + } + public void remove(AccessSection section) { if (section != null) { accessSections.remove(section.getName()); @@ -420,6 +428,7 @@ public class ProjectConfig extends VersionedMetaData { loadAccountsSection(rc, groupsByName); loadContributorAgreements(rc, groupsByName); loadAccessSections(rc, groupsByName); + loadBranchOrderSection(rc); loadNotifySections(rc, groupsByName); loadLabelSections(rc); loadCommentLinkSections(rc); @@ -570,6 +579,13 @@ public class ProjectConfig extends VersionedMetaData { } } + private void loadBranchOrderSection(Config rc) { + if (rc.getSections().contains(BRANCH_ORDER)) { + branchOrderSection = new BranchOrderSection( + rc.getStringList(BRANCH_ORDER, null, BRANCH)); + } + } + private List loadPermissionRules(Config rc, String section, String subsection, String varName, Map groupsByName, diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java index f6b96d791e..715419d8d0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java @@ -40,6 +40,7 @@ import com.google.gerrit.server.account.CapabilityCollection; import com.google.gerrit.server.account.GroupMembership; import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.SitePaths; +import com.google.gerrit.server.git.BranchOrderSection; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.ProjectLevelConfig; @@ -445,6 +446,16 @@ public class ProjectState { return ImmutableList.copyOf(cls.values()); } + public BranchOrderSection getBranchOrderSection() { + for (ProjectState s : tree()) { + BranchOrderSection section = s.getConfig().getBranchOrderSection(); + if (section != null) { + return section; + } + } + return null; + } + public ThemeInfo getTheme() { ThemeInfo theme = this.theme; if (theme == null) {