Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/tracker/field_helpers.py b/tracker/field_helpers.py
index d15f5e0..bd05cc0 100644
--- a/tracker/field_helpers.py
+++ b/tracker/field_helpers.py
@@ -1,7 +1,6 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 """Helper functions for custom field sevlets."""
 from __future__ import print_function
@@ -12,6 +11,9 @@
 import itertools
 import logging
 import re
+import settings
+
+from google.appengine.api import app_identity
 
 from features import autolink_constants
 from framework import authdata
@@ -21,7 +23,7 @@
 from framework import permissions
 from framework import timestr
 from framework import validate
-from proto import tracker_pb2
+from mrproto import tracker_pb2
 from services import config_svc
 from tracker import tracker_bizobj
 
@@ -39,9 +41,9 @@
 
 
 def ListApplicableFieldDefs(issues, config):
-  # type: (Sequence[proto.tracker_pb2.Issue],
-  #     proto.tracker_pb2.ProjectIssueConfig) ->
-  #     Sequence[proto.tracker_pb2.FieldDef]
+  # type: (Sequence[mrproto.tracker_pb2.Issue],
+  #     mrproto.tracker_pb2.ProjectIssueConfig) ->
+  #     Sequence[mrproto.tracker_pb2.FieldDef]
   """Return the applicable FieldDefs for the given issues. """
   issue_labels = []
   issue_approval_ids = []
@@ -280,9 +282,39 @@
   return field_values
 
 
+def ValidateLabels(cnxn, services, project_id, labels, ezt_errors=None):
+  """Validate labels to block creation of new labels for the Chromium project in
+    Monorail and return an error string or None.
+
+  Args:
+    cnxn: MonorailConnection object.
+    services: Services object referencing services that can be queried.
+    project_id: Project ID.
+    labels: List of labels to be validated.
+
+  Returns:
+    A string containing an error message if there was one.
+  """
+  if settings.unit_test_mode or project_id in settings.label_freeze_project_ids:
+    new_labels = [
+        l for l in labels if services.config.LookupLabelID(
+            cnxn, project_id, l, autocreate=False, case_sensitive=False) is None
+        and not settings.is_label_allowed(project_id, l)
+    ]
+    if len(new_labels) > 0:
+      err_msg = (
+          "The creation of new labels is blocked for the Chromium project"
+          " in Monorail. To continue with editing your issue, please"
+          " remove: {} label(s).").format(", ".join(new_labels))
+      if ezt_errors is not None:
+        ezt_errors.labels = err_msg
+      return err_msg
+  return None
+
+
 def ValidateCustomFieldValue(cnxn, project, services, field_def, field_val):
-  # type: (MonorailConnection, proto.tracker_pb2.Project, Services,
-  #     proto.tracker_pb2.FieldDef, proto.tracker_pb2.FieldValue) -> str
+  # type: (MonorailConnection, mrproto.tracker_pb2.Project, Services,
+  #     mrproto.tracker_pb2.FieldDef, mrproto.tracker_pb2.FieldValue) -> str
   """Validate one custom field value and return an error string or None.
 
   Args:
@@ -353,9 +385,9 @@
 def ValidateCustomFields(
     cnxn, services, field_values, config, project, ezt_errors=None, issue=None):
   # type: (MonorailConnection, Services,
-  #     Collection[proto.tracker_pb2.FieldValue],
-  #     proto.tracker_pb2.ProjectConfig, proto.tracker_pb2.Project,
-  #     Optional[EZTError], Optional[proto.tracker_pb2.Issue]) ->
+  #     Collection[mrproto.tracker_pb2.FieldValue],
+  #     mrproto.tracker_pb2.ProjectConfig, mrproto.tracker_pb2.Project,
+  #     Optional[EZTError], Optional[mrproto.tracker_pb2.Issue]) ->
   #     Sequence[str]
   """Validate given fields and report problems in error messages."""
   fds_by_id = {fd.field_id: fd for fd in config.field_defs}