Add REST endpoint to update an existing label
Bug: Issue 11522 Signed-off-by: Edwin Kempin <ekempin@google.com> Change-Id: Ic50e7fc1cf4daedfb8c7f0ae6458a807146ade16
This commit is contained in:
		| @@ -3139,6 +3139,61 @@ returned that describes the label. | |||||||
|   } |   } | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
|  | [[set-label]] | ||||||
|  | === Set Label | ||||||
|  | -- | ||||||
|  | 'PUT /projects/link:#project-name[\{project-name\}]/labels/link:#label-name[\{label-name\}]' | ||||||
|  | -- | ||||||
|  |  | ||||||
|  | Updates the definition of a label that is defined in this project. | ||||||
|  |  | ||||||
|  | The calling user must have write access to the `refs/meta/config` branch of the | ||||||
|  | project. | ||||||
|  |  | ||||||
|  | Properties which are not set in the input entity are not modified. | ||||||
|  |  | ||||||
|  | .Request | ||||||
|  | ---- | ||||||
|  |   PUT /projects/All-Projects/labels/Code-Review HTTP/1.0 | ||||||
|  |   Content-Type: application/json; charset=UTF-8 | ||||||
|  |  | ||||||
|  |   { | ||||||
|  |     "commit_message": "Ignore self approvals for Code-Review label", | ||||||
|  |     "ignore_self_approval": true | ||||||
|  |   } | ||||||
|  | ---- | ||||||
|  |  | ||||||
|  | As response a link:#label-definition-info[LabelDefinitionInfo] entity is | ||||||
|  | returned that describes the updated label. | ||||||
|  |  | ||||||
|  | .Response | ||||||
|  | ---- | ||||||
|  |   HTTP/1.1 200 OK | ||||||
|  |   Content-Disposition: attachment | ||||||
|  |   Content-Type: application/json; charset=UTF-8 | ||||||
|  |  | ||||||
|  |   )]}' | ||||||
|  |   { | ||||||
|  |     "name": "Code-Review", | ||||||
|  |     "project": "All-Projects", | ||||||
|  |     "function": "MaxWithBlock", | ||||||
|  |     "values": { | ||||||
|  |       " 0": "No score", | ||||||
|  |       "-1": "I would prefer this is not merged as is", | ||||||
|  |       "-2": "This shall not be merged", | ||||||
|  |       "+1": "Looks good to me, but someone else must approve", | ||||||
|  |       "+2": "Looks good to me, approved" | ||||||
|  |     }, | ||||||
|  |     "default_value": 0, | ||||||
|  |     "can_override": true, | ||||||
|  |     "copy_min_score": true, | ||||||
|  |     "copy_all_scores_if_no_change": true, | ||||||
|  |     "copy_all_scores_on_trivial_rebase": true, | ||||||
|  |     "allow_post_submit": true, | ||||||
|  |     "ignore_self_approval": true | ||||||
|  |   } | ||||||
|  | ---- | ||||||
|  |  | ||||||
|  |  | ||||||
| [[ids]] | [[ids]] | ||||||
| == IDs | == IDs | ||||||
| @@ -3735,6 +3790,66 @@ Whether link:config-labels.html#label_ignoreSelfApproval[ignoreSelfApproval] is | |||||||
| set on the label. | set on the label. | ||||||
| |============================= | |============================= | ||||||
|  |  | ||||||
|  | [[label-definition-input]] | ||||||
|  | === LabelDefinitionInput | ||||||
|  | The `LabelTypeInput` entity describes a link:config-labels.html[ | ||||||
|  | review label]. | ||||||
|  |  | ||||||
|  | [options="header",cols="1,^2,4"] | ||||||
|  | |============================= | ||||||
|  | |Field Name      ||Description | ||||||
|  | |`commit_message`|optional| | ||||||
|  | Message that should be used to commit the change of the label in the | ||||||
|  | `project.config` file to the `refs/meta/config` branch. | ||||||
|  | |`name`          |optional| | ||||||
|  | The new link:config-labels.html#label_name[name] of the label. | ||||||
|  | |`function`      |optional| | ||||||
|  | The new link:config-labels.html#label_function[function] of the label (can be | ||||||
|  | `MaxWithBlock`, `AnyWithBlock`, `MaxNoBlock`, `NoBlock`, `NoOp` and `PatchSetLock`. | ||||||
|  | |`values`        |optional| | ||||||
|  | The new link:config-labels.html#label_value[values] of the label as a map of | ||||||
|  | label value to value description. The label values are formatted strings, e.g. | ||||||
|  | "+1" instead of "1", " 0" instead of "0". | ||||||
|  | |`default_value` |optional| | ||||||
|  | The new link:config-labels.html#label_defaultValue[default value] of the label | ||||||
|  | (as integer). | ||||||
|  | |`branches`      |optional| | ||||||
|  | The new branches for which the label applies as a list of | ||||||
|  | link:config-labels.html#label_branch[branches]. A branch can be a ref, a ref | ||||||
|  | pattern or a regular expression. If not set, the label applies for all | ||||||
|  | branches. | ||||||
|  | |`can_override`  |optional| | ||||||
|  | Whether this label can be link:config-labels.html#label_canOverride[overridden] | ||||||
|  | by child projects. | ||||||
|  | |`copy_any_score`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyAnyScore[copyAnyScore] is set on the | ||||||
|  | label. | ||||||
|  | |`copy_min_score`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyMinScore[copyMinScore] is set on the | ||||||
|  | label. | ||||||
|  | |`copy_max_score`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyMaxScore[copyMaxScore] is set on the | ||||||
|  | label. | ||||||
|  | |`copy_all_scores_if_no_change`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyAllScoresIfNoChange[ | ||||||
|  | copyAllScoresIfNoChange] is set on the label. | ||||||
|  | |`copy_all_scores_if_no_code_change`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyAllScoresIfNoCodeChange[ | ||||||
|  | copyAllScoresIfNoCodeChange] is set on the label. | ||||||
|  | |`copy_all_scores_on_trivial_rebase`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyAllScoresOnTrivialRebase[ | ||||||
|  | copyAllScoresOnTrivialRebase] is set on the label. | ||||||
|  | |`copy_all_scores_on_merge_first_parent_update`|optional| | ||||||
|  | Whether link:config-labels.html#label_copyAllScoresOnMergeFirstParentUpdate[ | ||||||
|  | copyAllScoresOnMergeFirstParentUpdate] is set on the label. | ||||||
|  | |`allow_post_submit`|optional| | ||||||
|  | Whether link:config-labels.html#label_allowPostSubmit[allowPostSubmit] is set | ||||||
|  | on the label. | ||||||
|  | |`ignore_self_approval`|optional| | ||||||
|  | Whether link:config-labels.html#label_ignoreSelfApproval[ignoreSelfApproval] is | ||||||
|  | set on the label. | ||||||
|  | |============================= | ||||||
|  |  | ||||||
| [[label-type-info]] | [[label-type-info]] | ||||||
| === LabelTypeInfo | === LabelTypeInfo | ||||||
| The `LabelTypeInfo` entity contains metadata about the labels that a | The `LabelTypeInfo` entity contains metadata about the labels that a | ||||||
|   | |||||||
| @@ -157,6 +157,10 @@ public class LabelType { | |||||||
|     return name; |     return name; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public void setName(String name) { | ||||||
|  |     this.name = checkName(name); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public boolean matches(PatchSetApproval psa) { |   public boolean matches(PatchSetApproval psa) { | ||||||
|     return psa.labelId().get().equalsIgnoreCase(name); |     return psa.labelId().get().equalsIgnoreCase(name); | ||||||
|   } |   } | ||||||
| @@ -199,7 +203,7 @@ public class LabelType { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public void setRefPatterns(List<String> refPatterns) { |   public void setRefPatterns(List<String> refPatterns) { | ||||||
|     if (refPatterns != null) { |     if (refPatterns != null && !refPatterns.isEmpty()) { | ||||||
|       this.refPatterns = |       this.refPatterns = | ||||||
|           refPatterns.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList)); |           refPatterns.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList)); | ||||||
|     } else { |     } else { | ||||||
| @@ -211,6 +215,10 @@ public class LabelType { | |||||||
|     return values; |     return values; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public void setValues(List<LabelValue> values) { | ||||||
|  |     this.values = sortValues(values); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public LabelValue getMin() { |   public LabelValue getMin() { | ||||||
|     if (values.isEmpty()) { |     if (values.isEmpty()) { | ||||||
|       return null; |       return null; | ||||||
|   | |||||||
| @@ -15,12 +15,15 @@ | |||||||
| package com.google.gerrit.extensions.api.projects; | package com.google.gerrit.extensions.api.projects; | ||||||
|  |  | ||||||
| import com.google.gerrit.extensions.common.LabelDefinitionInfo; | import com.google.gerrit.extensions.common.LabelDefinitionInfo; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInput; | ||||||
| import com.google.gerrit.extensions.restapi.NotImplementedException; | import com.google.gerrit.extensions.restapi.NotImplementedException; | ||||||
| import com.google.gerrit.extensions.restapi.RestApiException; | import com.google.gerrit.extensions.restapi.RestApiException; | ||||||
|  |  | ||||||
| public interface LabelApi { | public interface LabelApi { | ||||||
|   LabelDefinitionInfo get() throws RestApiException; |   LabelDefinitionInfo get() throws RestApiException; | ||||||
|  |  | ||||||
|  |   LabelDefinitionInfo update(LabelDefinitionInput input) throws RestApiException; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * A default implementation which allows source compatibility when adding new methods to the |    * A default implementation which allows source compatibility when adding new methods to the | ||||||
|    * interface. |    * interface. | ||||||
| @@ -30,5 +33,10 @@ public interface LabelApi { | |||||||
|     public LabelDefinitionInfo get() throws RestApiException { |     public LabelDefinitionInfo get() throws RestApiException { | ||||||
|       throw new NotImplementedException(); |       throw new NotImplementedException(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LabelDefinitionInfo update(LabelDefinitionInput input) throws RestApiException { | ||||||
|  |       throw new NotImplementedException(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,37 @@ | |||||||
|  | // Copyright (C) 2019 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.extensions.common; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | public class LabelDefinitionInput { | ||||||
|  |   public String commitMessage; | ||||||
|  |   public String name; | ||||||
|  |   public String function; | ||||||
|  |   public Map<String, String> values; | ||||||
|  |   public Short defaultValue; | ||||||
|  |   public List<String> branches; | ||||||
|  |   public Boolean canOverride; | ||||||
|  |   public Boolean copyAnyScore; | ||||||
|  |   public Boolean copyMinScore; | ||||||
|  |   public Boolean copyMaxScore; | ||||||
|  |   public Boolean copyAllScoresIfNoChange; | ||||||
|  |   public Boolean copyAllScoresIfNoCodeChange; | ||||||
|  |   public Boolean copyAllScoresOnTrivialRebase; | ||||||
|  |   public Boolean copyAllScoresOnMergeFirstParentUpdate; | ||||||
|  |   public Boolean allowPostSubmit; | ||||||
|  |   public Boolean ignoreSelfApproval; | ||||||
|  | } | ||||||
| @@ -18,9 +18,11 @@ import static com.google.gerrit.server.api.ApiUtil.asRestApiException; | |||||||
|  |  | ||||||
| import com.google.gerrit.extensions.api.projects.LabelApi; | import com.google.gerrit.extensions.api.projects.LabelApi; | ||||||
| import com.google.gerrit.extensions.common.LabelDefinitionInfo; | import com.google.gerrit.extensions.common.LabelDefinitionInfo; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInput; | ||||||
| import com.google.gerrit.extensions.restapi.RestApiException; | import com.google.gerrit.extensions.restapi.RestApiException; | ||||||
| import com.google.gerrit.server.project.LabelResource; | import com.google.gerrit.server.project.LabelResource; | ||||||
| import com.google.gerrit.server.restapi.project.GetLabel; | import com.google.gerrit.server.restapi.project.GetLabel; | ||||||
|  | import com.google.gerrit.server.restapi.project.SetLabel; | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
| import com.google.inject.assistedinject.Assisted; | import com.google.inject.assistedinject.Assisted; | ||||||
|  |  | ||||||
| @@ -30,11 +32,13 @@ public class LabelApiImpl implements LabelApi { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   private final GetLabel getLabel; |   private final GetLabel getLabel; | ||||||
|  |   private final SetLabel setLabel; | ||||||
|   private final LabelResource rsrc; |   private final LabelResource rsrc; | ||||||
|  |  | ||||||
|   @Inject |   @Inject | ||||||
|   LabelApiImpl(GetLabel getLabel, @Assisted LabelResource rsrc) { |   LabelApiImpl(GetLabel getLabel, SetLabel setLabel, @Assisted LabelResource rsrc) { | ||||||
|     this.getLabel = getLabel; |     this.getLabel = getLabel; | ||||||
|  |     this.setLabel = setLabel; | ||||||
|     this.rsrc = rsrc; |     this.rsrc = rsrc; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -46,4 +50,13 @@ public class LabelApiImpl implements LabelApi { | |||||||
|       throw asRestApiException("Cannot get label", e); |       throw asRestApiException("Cannot get label", e); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public LabelDefinitionInfo update(LabelDefinitionInput input) throws RestApiException { | ||||||
|  |     try { | ||||||
|  |       return setLabel.apply(rsrc, input).value(); | ||||||
|  |     } catch (Exception e) { | ||||||
|  |       throw asRestApiException("Cannot update label", e); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1488,6 +1488,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError. | |||||||
|       List<String> refPatterns = label.getRefPatterns(); |       List<String> refPatterns = label.getRefPatterns(); | ||||||
|       if (refPatterns != null && !refPatterns.isEmpty()) { |       if (refPatterns != null && !refPatterns.isEmpty()) { | ||||||
|         rc.setStringList(LABEL, name, KEY_BRANCH, refPatterns); |         rc.setStringList(LABEL, name, KEY_BRANCH, refPatterns); | ||||||
|  |       } else { | ||||||
|  |         rc.unset(LABEL, name, KEY_BRANCH); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -69,6 +69,7 @@ public class Module extends RestApiModule { | |||||||
|  |  | ||||||
|     child(PROJECT_KIND, "labels").to(LabelsCollection.class); |     child(PROJECT_KIND, "labels").to(LabelsCollection.class); | ||||||
|     get(LABEL_KIND).to(GetLabel.class); |     get(LABEL_KIND).to(GetLabel.class); | ||||||
|  |     put(LABEL_KIND).to(SetLabel.class); | ||||||
|  |  | ||||||
|     get(PROJECT_KIND, "HEAD").to(GetHead.class); |     get(PROJECT_KIND, "HEAD").to(GetHead.class); | ||||||
|     put(PROJECT_KIND, "HEAD").to(SetHead.class); |     put(PROJECT_KIND, "HEAD").to(SetHead.class); | ||||||
|   | |||||||
							
								
								
									
										239
									
								
								java/com/google/gerrit/server/restapi/project/SetLabel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								java/com/google/gerrit/server/restapi/project/SetLabel.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,239 @@ | |||||||
|  | // Copyright (C) 2019 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.restapi.project; | ||||||
|  |  | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | import com.google.common.primitives.Shorts; | ||||||
|  | import com.google.gerrit.common.data.LabelFunction; | ||||||
|  | import com.google.gerrit.common.data.LabelType; | ||||||
|  | import com.google.gerrit.common.data.LabelValue; | ||||||
|  | import com.google.gerrit.common.data.PermissionRule; | ||||||
|  | import com.google.gerrit.entities.RefNames; | ||||||
|  | import com.google.gerrit.exceptions.InvalidNameException; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInfo; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInput; | ||||||
|  | import com.google.gerrit.extensions.restapi.AuthException; | ||||||
|  | import com.google.gerrit.extensions.restapi.BadRequestException; | ||||||
|  | import com.google.gerrit.extensions.restapi.ResourceConflictException; | ||||||
|  | import com.google.gerrit.extensions.restapi.Response; | ||||||
|  | import com.google.gerrit.extensions.restapi.RestModifyView; | ||||||
|  | import com.google.gerrit.server.git.meta.MetaDataUpdate; | ||||||
|  | import com.google.gerrit.server.permissions.PermissionBackend; | ||||||
|  | import com.google.gerrit.server.permissions.PermissionBackendException; | ||||||
|  | import com.google.gerrit.server.permissions.ProjectPermission; | ||||||
|  | import com.google.gerrit.server.project.LabelDefinitionJson; | ||||||
|  | import com.google.gerrit.server.project.LabelResource; | ||||||
|  | import com.google.gerrit.server.project.ProjectCache; | ||||||
|  | import com.google.gerrit.server.project.ProjectConfig; | ||||||
|  | import com.google.gerrit.server.project.RefPattern; | ||||||
|  | import com.google.inject.Inject; | ||||||
|  | import com.google.inject.Singleton; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map.Entry; | ||||||
|  | import java.util.Optional; | ||||||
|  | import org.eclipse.jgit.errors.ConfigInvalidException; | ||||||
|  |  | ||||||
|  | @Singleton | ||||||
|  | public class SetLabel implements RestModifyView<LabelResource, LabelDefinitionInput> { | ||||||
|  |   private final PermissionBackend permissionBackend; | ||||||
|  |   private final MetaDataUpdate.User updateFactory; | ||||||
|  |   private final ProjectConfig.Factory projectConfigFactory; | ||||||
|  |   private final ProjectCache projectCache; | ||||||
|  |  | ||||||
|  |   @Inject | ||||||
|  |   public SetLabel( | ||||||
|  |       PermissionBackend permissionBackend, | ||||||
|  |       MetaDataUpdate.User updateFactory, | ||||||
|  |       ProjectConfig.Factory projectConfigFactory, | ||||||
|  |       ProjectCache projectCache) { | ||||||
|  |     this.permissionBackend = permissionBackend; | ||||||
|  |     this.updateFactory = updateFactory; | ||||||
|  |     this.projectConfigFactory = projectConfigFactory; | ||||||
|  |     this.projectCache = projectCache; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public Response<LabelDefinitionInfo> apply(LabelResource rsrc, LabelDefinitionInput input) | ||||||
|  |       throws AuthException, BadRequestException, ResourceConflictException, | ||||||
|  |           PermissionBackendException, IOException, ConfigInvalidException { | ||||||
|  |     permissionBackend | ||||||
|  |         .currentUser() | ||||||
|  |         .project(rsrc.getProject().getNameKey()) | ||||||
|  |         .check(ProjectPermission.WRITE_CONFIG); | ||||||
|  |  | ||||||
|  |     if (input == null) { | ||||||
|  |       input = new LabelDefinitionInput(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     LabelType labelType = rsrc.getLabelType(); | ||||||
|  |  | ||||||
|  |     try (MetaDataUpdate md = updateFactory.create(rsrc.getProject().getNameKey())) { | ||||||
|  |       boolean dirty = false; | ||||||
|  |  | ||||||
|  |       ProjectConfig config = projectConfigFactory.read(md); | ||||||
|  |       config.getLabelSections().remove(labelType.getName()); | ||||||
|  |  | ||||||
|  |       if (input.name != null) { | ||||||
|  |         String newName = input.name.trim(); | ||||||
|  |         if (newName.isEmpty()) { | ||||||
|  |           throw new BadRequestException("name cannot be empty"); | ||||||
|  |         } | ||||||
|  |         if (!newName.equals(labelType.getName())) { | ||||||
|  |           if (config.getLabelSections().containsKey(newName)) { | ||||||
|  |             throw new ResourceConflictException("name " + newName + " already in use"); | ||||||
|  |           } | ||||||
|  |           try { | ||||||
|  |             labelType.setName(newName); | ||||||
|  |           } catch (IllegalArgumentException e) { | ||||||
|  |             throw new BadRequestException("invalid name: " + input.name, e); | ||||||
|  |           } | ||||||
|  |           dirty = true; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.function != null) { | ||||||
|  |         String newFunctionName = input.function.trim(); | ||||||
|  |         if (newFunctionName.isEmpty()) { | ||||||
|  |           throw new BadRequestException("function cannot be empty"); | ||||||
|  |         } | ||||||
|  |         Optional<LabelFunction> newFunction = LabelFunction.parse(newFunctionName); | ||||||
|  |         if (!newFunction.isPresent()) { | ||||||
|  |           throw new BadRequestException("unknown function: " + input.function); | ||||||
|  |         } | ||||||
|  |         labelType.setFunction(newFunction.get()); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.values != null) { | ||||||
|  |         if (input.values.isEmpty()) { | ||||||
|  |           throw new BadRequestException("values cannot be empty"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         List<LabelValue> newValues = new ArrayList<>(); | ||||||
|  |         for (Entry<String, String> e : input.values.entrySet()) { | ||||||
|  |           short value; | ||||||
|  |           try { | ||||||
|  |             value = Shorts.checkedCast(PermissionRule.parseInt(e.getKey().trim())); | ||||||
|  |           } catch (NumberFormatException ex) { | ||||||
|  |             throw new BadRequestException("invalid value: " + e.getKey(), ex); | ||||||
|  |           } | ||||||
|  |           String valueDescription = e.getValue().trim(); | ||||||
|  |           if (valueDescription.isEmpty()) { | ||||||
|  |             throw new BadRequestException( | ||||||
|  |                 "description for value '" + e.getKey() + "' cannot be empty"); | ||||||
|  |           } | ||||||
|  |           newValues.add(new LabelValue(value, valueDescription)); | ||||||
|  |         } | ||||||
|  |         labelType.setValues(newValues); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.defaultValue != null) { | ||||||
|  |         if (labelType.getValue(input.defaultValue) == null) { | ||||||
|  |           throw new BadRequestException("invalid default value: " + input.defaultValue); | ||||||
|  |         } | ||||||
|  |         labelType.setDefaultValue(input.defaultValue); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.branches != null) { | ||||||
|  |         List<String> newBranches = new ArrayList<>(); | ||||||
|  |         for (String branch : input.branches) { | ||||||
|  |           String newBranch = branch.trim(); | ||||||
|  |           if (newBranch.isEmpty()) { | ||||||
|  |             continue; | ||||||
|  |           } | ||||||
|  |           if (!RefPattern.isRE(newBranch) && !newBranch.startsWith(RefNames.REFS)) { | ||||||
|  |             newBranch = RefNames.REFS_HEADS + newBranch; | ||||||
|  |           } | ||||||
|  |           try { | ||||||
|  |             RefPattern.validate(newBranch); | ||||||
|  |           } catch (InvalidNameException e) { | ||||||
|  |             throw new BadRequestException("invalid branch: " + branch, e); | ||||||
|  |           } | ||||||
|  |           newBranches.add(newBranch); | ||||||
|  |         } | ||||||
|  |         labelType.setRefPatterns(newBranches); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.canOverride != null) { | ||||||
|  |         labelType.setCanOverride(input.canOverride); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyAnyScore != null) { | ||||||
|  |         labelType.setCopyAnyScore(input.copyAnyScore); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyMinScore != null) { | ||||||
|  |         labelType.setCopyMinScore(input.copyMinScore); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyMaxScore != null) { | ||||||
|  |         labelType.setCopyMaxScore(input.copyMaxScore); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyAllScoresIfNoChange != null) { | ||||||
|  |         labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyAllScoresIfNoCodeChange != null) { | ||||||
|  |         labelType.setCopyAllScoresIfNoCodeChange(input.copyAllScoresIfNoCodeChange); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyAllScoresOnTrivialRebase != null) { | ||||||
|  |         labelType.setCopyAllScoresOnTrivialRebase(input.copyAllScoresOnTrivialRebase); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.copyAllScoresOnMergeFirstParentUpdate != null) { | ||||||
|  |         labelType.setCopyAllScoresOnMergeFirstParentUpdate( | ||||||
|  |             input.copyAllScoresOnMergeFirstParentUpdate); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.allowPostSubmit != null) { | ||||||
|  |         labelType.setAllowPostSubmit(input.allowPostSubmit); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (input.ignoreSelfApproval != null) { | ||||||
|  |         labelType.setIgnoreSelfApproval(input.ignoreSelfApproval); | ||||||
|  |         dirty = true; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (dirty) { | ||||||
|  |         config.getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |  | ||||||
|  |         if (input.commitMessage != null) { | ||||||
|  |           md.setMessage(Strings.emptyToNull(input.commitMessage.trim())); | ||||||
|  |         } else { | ||||||
|  |           md.setMessage("Update label"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         config.commit(md); | ||||||
|  |         projectCache.evict(rsrc.getProject().getProjectState().getProject()); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return Response.ok(LabelDefinitionJson.format(rsrc.getProject().getNameKey(), labelType)); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,849 @@ | |||||||
|  | // Copyright (C) 2019 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.acceptance.rest.project; | ||||||
|  |  | ||||||
|  | import static com.google.common.truth.Truth.assertThat; | ||||||
|  | import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow; | ||||||
|  | import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; | ||||||
|  | import static com.google.gerrit.testing.GerritJUnit.assertThrows; | ||||||
|  |  | ||||||
|  | import com.google.common.collect.ImmutableList; | ||||||
|  | import com.google.common.collect.ImmutableMap; | ||||||
|  | import com.google.gerrit.acceptance.AbstractDaemonTest; | ||||||
|  | import com.google.gerrit.acceptance.NoHttpd; | ||||||
|  | import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; | ||||||
|  | import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations; | ||||||
|  | import com.google.gerrit.common.data.LabelFunction; | ||||||
|  | import com.google.gerrit.common.data.LabelType; | ||||||
|  | import com.google.gerrit.common.data.Permission; | ||||||
|  | import com.google.gerrit.entities.RefNames; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInfo; | ||||||
|  | import com.google.gerrit.extensions.common.LabelDefinitionInput; | ||||||
|  | import com.google.gerrit.extensions.restapi.AuthException; | ||||||
|  | import com.google.gerrit.extensions.restapi.BadRequestException; | ||||||
|  | import com.google.gerrit.extensions.restapi.ResourceConflictException; | ||||||
|  | import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | ||||||
|  | import com.google.inject.Inject; | ||||||
|  | import org.eclipse.jgit.revwalk.RevCommit; | ||||||
|  | import org.junit.Test; | ||||||
|  |  | ||||||
|  | @NoHttpd | ||||||
|  | public class SetLabelIT extends AbstractDaemonTest { | ||||||
|  |   @Inject private RequestScopeOperations requestScopeOperations; | ||||||
|  |   @Inject private ProjectOperations projectOperations; | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void notAllowed() throws Exception { | ||||||
|  |     projectOperations | ||||||
|  |         .project(allProjects) | ||||||
|  |         .forUpdate() | ||||||
|  |         .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(REGISTERED_USERS)) | ||||||
|  |         .update(); | ||||||
|  |  | ||||||
|  |     requestScopeOperations.setApiUser(user.id()); | ||||||
|  |     AuthException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             AuthException.class, | ||||||
|  |             () -> | ||||||
|  |                 gApi.projects() | ||||||
|  |                     .name(allProjects.get()) | ||||||
|  |                     .label("Code-Review") | ||||||
|  |                     .update(new LabelDefinitionInput())); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("write refs/meta/config not permitted"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void updateName() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.name = "Foo-Review"; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.name).isEqualTo(input.name); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Foo-Review").get()).isNotNull(); | ||||||
|  |     assertThrows( | ||||||
|  |         ResourceNotFoundException.class, | ||||||
|  |         () -> gApi.projects().name(project.get()).label("Code-Review").get()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void nameIsTrimmed() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.name = " Foo-Review "; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.name).isEqualTo("Foo-Review"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Foo-Review").get()).isNotNull(); | ||||||
|  |     assertThrows( | ||||||
|  |         ResourceNotFoundException.class, | ||||||
|  |         () -> gApi.projects().name(project.get()).label("Code-Review").get()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetEmptyName() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.name = ""; | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("name cannot be empty"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetInvalidName() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.name = "INVALID_NAME"; | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("invalid name: " + input.name); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetNameIfNameClashes() throws Exception { | ||||||
|  |     configLabel("Foo-Review", LabelFunction.NO_OP); | ||||||
|  |     configLabel("Bar-Review", LabelFunction.NO_OP); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.name = "Bar-Review"; | ||||||
|  |  | ||||||
|  |     ResourceConflictException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             ResourceConflictException.class, | ||||||
|  |             () -> gApi.projects().name(project.get()).label("Foo-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("name " + input.name + " already in use"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void updateFunction() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = LabelFunction.NO_OP.getFunctionName(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.function).isEqualTo(input.function); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().function) | ||||||
|  |         .isEqualTo(input.function); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void functionIsTrimmed() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = " " + LabelFunction.NO_OP.getFunctionName() + " "; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.function).isEqualTo(LabelFunction.NO_OP.getFunctionName()); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().function) | ||||||
|  |         .isEqualTo(LabelFunction.NO_OP.getFunctionName()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetEmptyFunction() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = ""; | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("function cannot be empty"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetUnknownFunction() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = "UnknownFunction"; | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("unknown function: " + input.function); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetEmptyValues() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.values = ImmutableMap.of(); | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("values cannot be empty"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void updateValues() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     // Positive values can be specified as '<value>' or '+<value>'. | ||||||
|  |     input.values = | ||||||
|  |         ImmutableMap.of( | ||||||
|  |             "2", | ||||||
|  |             "Looks Very Good", | ||||||
|  |             "+1", | ||||||
|  |             "Looks Good", | ||||||
|  |             "0", | ||||||
|  |             "Don't Know", | ||||||
|  |             "-1", | ||||||
|  |             "Looks Bad", | ||||||
|  |             "-2", | ||||||
|  |             "Looks Very Bad"); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.values) | ||||||
|  |         .containsExactly( | ||||||
|  |             "+2", "Looks Very Good", | ||||||
|  |             "+1", "Looks Good", | ||||||
|  |             " 0", "Don't Know", | ||||||
|  |             "-1", "Looks Bad", | ||||||
|  |             "-2", "Looks Very Bad"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().values) | ||||||
|  |         .containsExactly( | ||||||
|  |             "+2", "Looks Very Good", | ||||||
|  |             "+1", "Looks Good", | ||||||
|  |             " 0", "Don't Know", | ||||||
|  |             "-1", "Looks Bad", | ||||||
|  |             "-2", "Looks Very Bad"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void valuesAndDescriptionsAreTrimmed() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     // Positive values can be specified as '<value>' or '+<value>'. | ||||||
|  |     input.values = | ||||||
|  |         ImmutableMap.of( | ||||||
|  |             " 2 ", | ||||||
|  |             " Looks Very Good ", | ||||||
|  |             " +1 ", | ||||||
|  |             " Looks Good ", | ||||||
|  |             " 0 ", | ||||||
|  |             " Don't Know ", | ||||||
|  |             " -1 ", | ||||||
|  |             " Looks Bad ", | ||||||
|  |             " -2 ", | ||||||
|  |             " Looks Very Bad "); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.values) | ||||||
|  |         .containsExactly( | ||||||
|  |             "+2", "Looks Very Good", | ||||||
|  |             "+1", "Looks Good", | ||||||
|  |             " 0", "Don't Know", | ||||||
|  |             "-1", "Looks Bad", | ||||||
|  |             "-2", "Looks Very Bad"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().values) | ||||||
|  |         .containsExactly( | ||||||
|  |             "+2", "Looks Very Good", | ||||||
|  |             "+1", "Looks Good", | ||||||
|  |             " 0", "Don't Know", | ||||||
|  |             "-1", "Looks Bad", | ||||||
|  |             "-2", "Looks Very Bad"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetInvalidValues() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.values = ImmutableMap.of("invalidValue", "description"); | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("invalid value: invalidValue"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetValueWithEmptyDescription() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.values = ImmutableMap.of("+1", ""); | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("description for value '+1' cannot be empty"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void updateDefaultValue() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.defaultValue = 1; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.defaultValue).isEqualTo(input.defaultValue); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().defaultValue) | ||||||
|  |         .isEqualTo(input.defaultValue); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetInvalidDefaultValue() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.defaultValue = 5; | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("invalid default value: " + input.defaultValue); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void updateBranches() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     // Branches can be full ref, ref pattern or regular expression. | ||||||
|  |     input.branches = | ||||||
|  |         ImmutableList.of("refs/heads/master", "refs/heads/foo/*", "^refs/heads/stable-.*"); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.branches).containsExactlyElementsIn(input.branches); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .containsExactlyElementsIn(input.branches); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void branchesAreTrimmed() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.branches = | ||||||
|  |         ImmutableList.of(" refs/heads/master ", " refs/heads/foo/* ", " ^refs/heads/stable-.* "); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.branches) | ||||||
|  |         .containsExactly("refs/heads/master", "refs/heads/foo/*", "^refs/heads/stable-.*"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .containsExactly("refs/heads/master", "refs/heads/foo/*", "^refs/heads/stable-.*"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void emptyBranchesAreIgnored() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.branches = ImmutableList.of("refs/heads/master", "", " "); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.branches).containsExactly("refs/heads/master"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .containsExactly("refs/heads/master"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void branchesCanBeUnset() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.branches = ImmutableList.of("refs/heads/master"); | ||||||
|  |     gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .isNotNull(); | ||||||
|  |  | ||||||
|  |     input.branches = ImmutableList.of(); | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.branches).isNull(); | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void cannotSetInvalidBranch() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.branches = ImmutableList.of("refs heads master"); | ||||||
|  |  | ||||||
|  |     BadRequestException thrown = | ||||||
|  |         assertThrows( | ||||||
|  |             BadRequestException.class, | ||||||
|  |             () -> gApi.projects().name(allProjects.get()).label("Code-Review").update(input)); | ||||||
|  |     assertThat(thrown).hasMessageThat().contains("invalid branch: refs heads master"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void branchesAreAutomaticallyPrefixedWithRefsHeads() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.branches = ImmutableList.of("master", "refs/meta/config"); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat(updatedLabel.branches).containsExactly("refs/heads/master", "refs/meta/config"); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(allProjects.get()).label("Code-Review").get().branches) | ||||||
|  |         .containsExactly("refs/heads/master", "refs/meta/config"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCanOverride() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCanOverride(false); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().canOverride).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.canOverride = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.canOverride).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().canOverride).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCanOverride() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().canOverride).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.canOverride = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.canOverride).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().canOverride).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyAnyScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAnyScore).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAnyScore = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAnyScore).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAnyScore).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyAnyScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyAnyScore(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAnyScore).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAnyScore = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAnyScore).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAnyScore).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyMinScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMinScore).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyMinScore = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyMinScore).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMinScore).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyMinScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyMinScore(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMinScore).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyMinScore = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyMinScore).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMinScore).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyMaxScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMaxScore).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyMaxScore = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyMaxScore).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMaxScore).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyMaxScore() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyMaxScore(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMaxScore).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyMaxScore = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyMaxScore).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyMaxScore).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyAllScoresIfNoChange() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyAllScoresIfNoChange(false); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoChange) | ||||||
|  |         .isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresIfNoChange = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresIfNoChange).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoChange) | ||||||
|  |         .isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyAllScoresIfNoChange() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoChange) | ||||||
|  |         .isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresIfNoChange = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresIfNoChange).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoChange) | ||||||
|  |         .isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyAllScoresIfNoCodeChange() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoCodeChange) | ||||||
|  |         .isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresIfNoCodeChange = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresIfNoCodeChange).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoCodeChange) | ||||||
|  |         .isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyAllScoresIfNoCodeChange() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyAllScoresIfNoCodeChange(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoCodeChange) | ||||||
|  |         .isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresIfNoCodeChange = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresIfNoCodeChange).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresIfNoCodeChange) | ||||||
|  |         .isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyAllScoresOnTrivialRebase() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresOnTrivialRebase) | ||||||
|  |         .isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresOnTrivialRebase = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresOnTrivialRebase).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresOnTrivialRebase) | ||||||
|  |         .isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyAllScoresOnTrivialRebase() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyAllScoresOnTrivialRebase(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresOnTrivialRebase) | ||||||
|  |         .isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresOnTrivialRebase = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresOnTrivialRebase).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().copyAllScoresOnTrivialRebase) | ||||||
|  |         .isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setCopyAllScoresOnMergeFirstParentUpdate() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat( | ||||||
|  |             gApi.projects() | ||||||
|  |                 .name(project.get()) | ||||||
|  |                 .label("foo") | ||||||
|  |                 .get() | ||||||
|  |                 .copyAllScoresOnMergeFirstParentUpdate) | ||||||
|  |         .isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresOnMergeFirstParentUpdate = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresOnMergeFirstParentUpdate).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat( | ||||||
|  |             gApi.projects() | ||||||
|  |                 .name(project.get()) | ||||||
|  |                 .label("foo") | ||||||
|  |                 .get() | ||||||
|  |                 .copyAllScoresOnMergeFirstParentUpdate) | ||||||
|  |         .isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetCopyAllScoresOnMergeFirstParentUpdate() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setCopyAllScoresOnMergeFirstParentUpdate(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat( | ||||||
|  |             gApi.projects() | ||||||
|  |                 .name(project.get()) | ||||||
|  |                 .label("foo") | ||||||
|  |                 .get() | ||||||
|  |                 .copyAllScoresOnMergeFirstParentUpdate) | ||||||
|  |         .isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.copyAllScoresOnMergeFirstParentUpdate = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.copyAllScoresOnMergeFirstParentUpdate).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat( | ||||||
|  |             gApi.projects() | ||||||
|  |                 .name(project.get()) | ||||||
|  |                 .label("foo") | ||||||
|  |                 .get() | ||||||
|  |                 .copyAllScoresOnMergeFirstParentUpdate) | ||||||
|  |         .isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setAllowPostSubmit() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setAllowPostSubmit(false); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().allowPostSubmit).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.allowPostSubmit = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.allowPostSubmit).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().allowPostSubmit).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetAllowPostSubmit() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().allowPostSubmit).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.allowPostSubmit = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.allowPostSubmit).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().allowPostSubmit).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void setIgnoreSelfApproval() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().ignoreSelfApproval).isNull(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.ignoreSelfApproval = true; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.ignoreSelfApproval).isTrue(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().ignoreSelfApproval).isTrue(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void unsetIgnoreSelfApproval() throws Exception { | ||||||
|  |     configLabel("foo", LabelFunction.NO_OP); | ||||||
|  |     try (ProjectConfigUpdate u = updateProject(project)) { | ||||||
|  |       LabelType labelType = u.getConfig().getLabelSections().get("foo"); | ||||||
|  |       labelType.setIgnoreSelfApproval(true); | ||||||
|  |       u.getConfig().getLabelSections().put(labelType.getName(), labelType); | ||||||
|  |       u.save(); | ||||||
|  |     } | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().ignoreSelfApproval).isTrue(); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.ignoreSelfApproval = false; | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects().name(project.get()).label("foo").update(input); | ||||||
|  |     assertThat(updatedLabel.ignoreSelfApproval).isNull(); | ||||||
|  |  | ||||||
|  |     assertThat(gApi.projects().name(project.get()).label("foo").get().ignoreSelfApproval).isNull(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void noOpUpdate() throws Exception { | ||||||
|  |     RevCommit refsMetaConfigHead = | ||||||
|  |         projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG); | ||||||
|  |  | ||||||
|  |     LabelDefinitionInfo updatedLabel = | ||||||
|  |         gApi.projects() | ||||||
|  |             .name(allProjects.get()) | ||||||
|  |             .label("Code-Review") | ||||||
|  |             .update(new LabelDefinitionInput()); | ||||||
|  |     LabelAssert.assertCodeReviewLabel(updatedLabel); | ||||||
|  |  | ||||||
|  |     LabelAssert.assertCodeReviewLabel( | ||||||
|  |         gApi.projects().name(allProjects.get()).label("Code-Review").get()); | ||||||
|  |  | ||||||
|  |     assertThat(projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG)) | ||||||
|  |         .isEqualTo(refsMetaConfigHead); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void defaultCommitMessage() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = LabelFunction.NO_OP.getFunctionName(); | ||||||
|  |     gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat( | ||||||
|  |             projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage()) | ||||||
|  |         .isEqualTo("Update label"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void withCommitMessage() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = LabelFunction.NO_OP.getFunctionName(); | ||||||
|  |     input.commitMessage = "Set NoOp function"; | ||||||
|  |     gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat( | ||||||
|  |             projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage()) | ||||||
|  |         .isEqualTo(input.commitMessage); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Test | ||||||
|  |   public void commitMessageIsTrimmed() throws Exception { | ||||||
|  |     LabelDefinitionInput input = new LabelDefinitionInput(); | ||||||
|  |     input.function = LabelFunction.NO_OP.getFunctionName(); | ||||||
|  |     input.commitMessage = " Set NoOp function "; | ||||||
|  |     gApi.projects().name(allProjects.get()).label("Code-Review").update(input); | ||||||
|  |     assertThat( | ||||||
|  |             projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage()) | ||||||
|  |         .isEqualTo("Set NoOp function"); | ||||||
|  |   } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Edwin Kempin
					Edwin Kempin