Jelajahi Sumber

metadata: allow a special "Revision: DEPS" syntax

This CL introduces a validation rule for "Revision: DEPS" syntax
so dependencies managed by DEPS and autorolled can use it to declare
their versioning metadata.

Bug: b/335761679
Change-Id: I0b4f99d281543f9295b122ac71036b06205a6168
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/5904321
Commit-Queue: Jiewei Qian <qjw@chromium.org>
Reviewed-by: Rachael Newitt <renewitt@google.com>
Jiewei Qian 10 bulan lalu
induk
melakukan
6af18461ad

+ 7 - 2
metadata/dependency_metadata.py

@@ -221,8 +221,8 @@ class DependencyMetadata:
         # If the repository is hosted somewhere (i.e. Chromium isn't the
         # If the repository is hosted somewhere (i.e. Chromium isn't the
         # canonical repositroy of the dependency), at least one of the fields
         # canonical repositroy of the dependency), at least one of the fields
         # Version, Date or Revision must be provided.
         # Version, Date or Revision must be provided.
-        if (not (self.is_canonical or self.version or self.date
-                 or self.revision)):
+        if (not (self.is_canonical or self.version or self.date or self.revision
+                 or self.revision_in_deps)):
             versioning_fields = [
             versioning_fields = [
                 known_fields.VERSION, known_fields.DATE, known_fields.REVISION
                 known_fields.VERSION, known_fields.DATE, known_fields.REVISION
             ]
             ]
@@ -307,6 +307,11 @@ class DependencyMetadata:
     def revision(self) -> Optional[str]:
     def revision(self) -> Optional[str]:
         return self._return_as_property(known_fields.REVISION)
         return self._return_as_property(known_fields.REVISION)
 
 
+    @property
+    def revision_in_deps(self) -> bool:
+        value = self._metadata.get(known_fields.REVISION, "")
+        return known_fields.REVISION.is_revision_in_deps(value)
+
     @property
     @property
     def license(self) -> Optional[List[str]]:
     def license(self) -> Optional[List[str]]:
         """Returns a list of license names."""
         """Returns a list of license names."""

+ 8 - 0
metadata/fields/custom/revision.py

@@ -22,6 +22,9 @@ import metadata.validation_result as vr
 
 
 HEX_PATTERN = re.compile(r"^[a-fA-F0-9]{7,40}$")
 HEX_PATTERN = re.compile(r"^[a-fA-F0-9]{7,40}$")
 
 
+# A special pattern to indicate that revision is written in DEPS file.
+DEPS_PATTERN = re.compile(r"^DEPS$")
+
 
 
 class RevisionField(field_types.SingleLineTextField):
 class RevisionField(field_types.SingleLineTextField):
     """Custom field for the revision."""
     """Custom field for the revision."""
@@ -29,6 +32,9 @@ class RevisionField(field_types.SingleLineTextField):
     def __init__(self):
     def __init__(self):
         super().__init__(name="Revision")
         super().__init__(name="Revision")
 
 
+    def is_revision_in_deps(self, value: str) -> bool:
+        return bool(DEPS_PATTERN.match(value))
+
     def narrow_type(self, value: str) -> Optional[str]:
     def narrow_type(self, value: str) -> Optional[str]:
         value = super().narrow_type(value)
         value = super().narrow_type(value)
         if not value:
         if not value:
@@ -52,6 +58,8 @@ class RevisionField(field_types.SingleLineTextField):
           - Non-empty value.
           - Non-empty value.
           - Valid hexadecimal format (length 7-40 characters).
           - Valid hexadecimal format (length 7-40 characters).
         """
         """
+        if self.is_revision_in_deps(value):
+            return None
 
 
         if util.is_unknown(value):
         if util.is_unknown(value):
             return vr.ValidationWarning(
             return vr.ValidationWarning(

+ 21 - 0
metadata/tests/dependency_metadata_test.py

@@ -218,6 +218,27 @@ class DependencyValidationTest(unittest.TestCase):
         # No errors for valid revision.
         # No errors for valid revision.
         self.assertEqual(len(results), 0)
         self.assertEqual(len(results), 0)
 
 
+    def test_valid_revision_in_deps(self):
+        """Check "Revision: DEPS" is acceptable."""
+
+        dependency = dm.DependencyMetadata()
+        dependency.add_entry(known_fields.NAME.get_name(), "Dependency")
+        dependency.add_entry(known_fields.URL.get_name(),
+                             "https://www.example.com")
+        dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
+        dependency.add_entry(known_fields.REVISION.get_name(), "DEPS")
+        dependency.add_entry(known_fields.LICENSE.get_name(), "Public Domain")
+        dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE")
+        dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no")
+        dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
+
+        results = dependency.validate(
+            source_file_dir=os.path.join(_THIS_DIR, "data"),
+            repo_root_dir=_THIS_DIR,
+        )
+        # No errors for no revision.
+        self.assertEqual(len(results), 0)
+
     def test_required_field(self):
     def test_required_field(self):
         """Check that a validation error is returned for a missing field."""
         """Check that a validation error is returned for a missing field."""
         dependency = dm.DependencyMetadata()
         dependency = dm.DependencyMetadata()