diff --git a/Documentation/config-labels.txt b/Documentation/config-labels.txt index a1cf9eee29..c3e09c4d3e 100644 --- a/Documentation/config-labels.txt +++ b/Documentation/config-labels.txt @@ -244,6 +244,30 @@ If false, the label cannot be overridden by child projects. Any configuration for this label in child projects will be ignored. Defaults to true. +[[label_branch]] +`label.Label-Name.branch` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default a given project's label applicable scope is all changes +on all branches of this project and its child projects. + +Label's applicable scope can be branch specific via configuration. +E.g. create a label `Video-Qualify` on parent project and configure +the `branch` as: + +==== + [label "Video-Qualify"] + branch = refs/heads/video-1.0/* + branch = refs/heads/video-1.1/Kino +==== + +Then *only* changes in above branch scope of parent project and child +projects will be affected by `Video-Qualify`. + +NOTE: The `branch` is independent from the branch scope defined in `access` +parts in `project.config` file. That means from the UI a user can always +assign permissions for that label on a branch, but this permission is then +ignored if the label doesn't apply for that branch. [[label_example]] Example diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java index db8bde9524..caf914d47d 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/LabelType.java @@ -103,6 +103,7 @@ public class LabelType { protected short maxPositive; private transient boolean canOverride; + private transient List refPatterns; private transient List intList; private transient Map byValue; @@ -157,10 +158,18 @@ public class LabelType { return canOverride; } + public List getRefPatterns() { + return refPatterns; + } + public void setCanOverride(boolean canOverride) { this.canOverride = canOverride; } + public void setRefPatterns(List refPatterns) { + this.refPatterns = refPatterns; + } + public List getValues() { return values; } 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 a803ddde52..3df559db5c 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 @@ -59,6 +59,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; @@ -127,6 +128,7 @@ public class ProjectConfig extends VersionedMetaData { private static final String KEY_COPY_MAX_SCORE = "copyMaxScore"; private static final String KEY_VALUE = "value"; private static final String KEY_CAN_OVERRIDE = "canOverride"; + private static final String KEY_Branch = "branch"; private static final Set LABEL_FUNCTIONS = ImmutableSet.of( "MaxWithBlock", "AnyWithBlock", "MaxNoBlock", "NoBlock", "NoOp"); @@ -651,10 +653,17 @@ public class ProjectConfig extends VersionedMetaData { rc.getBoolean(LABEL, name, KEY_COPY_MAX_SCORE, false)); label.setCanOverride( rc.getBoolean(LABEL, name, KEY_CAN_OVERRIDE, true)); + label.setRefPatterns(getStringListOrNull(rc, LABEL, name, KEY_Branch)); labelSections.put(name, label); } } + private List getStringListOrNull(Config rc, String section, + String subSection, String name) { + String[] ac = rc.getStringList(section, subSection, name); + return ac.length == 0 ? null : Arrays.asList(ac); + } + private void loadCommentLinkSections(Config rc) { Set subsections = rc.getSubsections(COMMENTLINK); commentLinkSections = Lists.newArrayListWithCapacity(subsections.size()); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java index 667a510924..decf90ad10 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java @@ -14,8 +14,11 @@ package com.google.gerrit.server.project; +import com.google.common.collect.Lists; +import com.google.gerrit.common.data.LabelType; import com.google.gerrit.common.data.LabelTypes; import com.google.gerrit.common.data.PermissionRange; +import com.google.gerrit.common.data.RefConfigSection; import com.google.gerrit.common.data.SubmitRecord; import com.google.gerrit.common.data.SubmitTypeRecord; import com.google.gerrit.reviewdb.client.Account; @@ -242,9 +245,28 @@ public class ChangeControl { && getRefControl().canUpload(); // as long as you can upload too } - /** All available label types for this project. */ + /** All available label types for this change. */ public LabelTypes getLabelTypes() { - return getProjectControl().getLabelTypes(); + String destBranch = getChange().getDest().get(); + List all = getProjectControl().getLabelTypes().getLabelTypes(); + + List r = Lists.newArrayListWithCapacity(all.size()); + for (LabelType l : all) { + List refs = l.getRefPatterns(); + if (refs == null) { + r.add(l); + } else { + for (String refPattern : refs) { + if (RefConfigSection.isValid(refPattern) + && match(destBranch, refPattern)) { + r.add(l); + break; + } + } + } + } + + return new LabelTypes(r); } /** All value ranges of any allowed label permission. */ @@ -403,6 +425,11 @@ public class ChangeControl { return resultsToSubmitRecord(evaluator.getSubmitRule(), results); } + private boolean match(String destBranch, String refPattern) { + return RefPatternMatcher.getMatcher(refPattern).match(destBranch, + this.getRefControl().getCurrentUser().getUserName()); + } + private List cannotSubmitDraft(ReviewDb db, PatchSet patchSet, ChangeData cd) { try { diff --git a/gerrit-server/src/main/java/gerrit/PRED_get_legacy_label_types_1.java b/gerrit-server/src/main/java/gerrit/PRED_get_legacy_label_types_1.java index 4b8954409a..698c11cee7 100644 --- a/gerrit-server/src/main/java/gerrit/PRED_get_legacy_label_types_1.java +++ b/gerrit-server/src/main/java/gerrit/PRED_get_legacy_label_types_1.java @@ -16,9 +16,7 @@ package gerrit; import com.google.gerrit.common.data.LabelType; import com.google.gerrit.common.data.LabelValue; -import com.google.gerrit.rules.PrologEnvironment; import com.google.gerrit.rules.StoredValues; -import com.google.gerrit.server.project.ProjectState; import com.googlecode.prolog_cafe.lang.IntegerTerm; import com.googlecode.prolog_cafe.lang.ListTerm; @@ -55,14 +53,8 @@ class PRED_get_legacy_label_types_1 extends Predicate.P1 { public Operation exec(Prolog engine) throws PrologException { engine.setB0(); Term a1 = arg1.dereference(); - - PrologEnvironment env = (PrologEnvironment) engine.control; - ProjectState state = env.getArgs().getProjectCache() - .get(StoredValues.CHANGE.get(engine).getDest().getParentKey()); - if (state == null) { - return engine.fail(); - } - List list = state.getLabelTypes().getLabelTypes(); + List list = + StoredValues.CHANGE_CONTROL.get(engine).getLabelTypes().getLabelTypes(); Term head = Prolog.Nil; for (int idx = list.size() - 1; 0 <= idx; idx--) { head = new ListTerm(export(list.get(idx)), head);