diff --git a/metadata/fields/custom/cpe_prefix.py b/metadata/fields/custom/cpe_prefix.py new file mode 100644 index 000000000..f3023af0e --- /dev/null +++ b/metadata/fields/custom/cpe_prefix.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# Copyright 2023 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. + +import os +import re +import sys +from typing import Union + +_THIS_DIR = os.path.abspath(os.path.dirname(__file__)) +# The repo's root directory. +_ROOT_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..", "..", "..")) + +# Add the repo's root directory for clearer imports. +sys.path.insert(0, _ROOT_DIR) + +import metadata.fields.types as field_types +import metadata.fields.util as util +import metadata.validation_result as vr + +_PATTERN_CPE_PREFIX = re.compile(r"^cpe:/.+:.+:.+(:.+)*$") + + +class CPEPrefixField(field_types.MetadataField): + """Custom field for the package's CPE.""" + def __init__(self): + super().__init__(name="CPEPrefix", one_liner=False) + + def validate(self, value: str) -> Union[vr.ValidationResult, None]: + """Checks the given value is either 'unknown', or a valid + CPE in the URI form `cpe:/::[:]`. + """ + if util.is_unknown(value) or util.matches(_PATTERN_CPE_PREFIX, value): + return None + + return vr.ValidationError( + f"{self._name} is '{value}' - must be either 'unknown', or in the form " + "'cpe:/::[:]'.") diff --git a/metadata/fields/known.py b/metadata/fields/known.py index 0146e6c51..abddf2b75 100644 --- a/metadata/fields/known.py +++ b/metadata/fields/known.py @@ -14,6 +14,7 @@ _ROOT_DIR = os.path.abspath(os.path.join(_THIS_DIR, "..", "..")) # Add the repo's root directory for clearer imports. sys.path.insert(0, _ROOT_DIR) +import metadata.fields.custom.cpe_prefix import metadata.fields.custom.date import metadata.fields.types as field_types @@ -32,6 +33,7 @@ LICENSE_ANDROID_COMPATIBLE = field_types.YesNoField( "License Android Compatible") # Custom fields. +CPE_PREFIX = metadata.fields.custom.cpe_prefix.CPEPrefixField() DATE = metadata.fields.custom.date.DateField() ALL_FIELDS = ( @@ -42,6 +44,7 @@ ALL_FIELDS = ( SECURITY_CRITICAL, SHIPPED, LICENSE_ANDROID_COMPATIBLE, + CPE_PREFIX, DESCRIPTION, LOCAL_MODIFICATIONS, ) diff --git a/metadata/tests/fields_test.py b/metadata/tests/fields_test.py index d335b2276..ddd99d1cb 100644 --- a/metadata/tests/fields_test.py +++ b/metadata/tests/fields_test.py @@ -66,6 +66,15 @@ class FieldValidationTest(unittest.TestCase): warning_values=["Yes?", "not"], ) + def test_cpe_prefix_validation(self): + self._run_field_validation( + field=known_fields.CPE_PREFIX, + valid_values=[ + "unknown", "cpe:/a:sqlite:sqlite:3.0.0", "cpe:/a:sqlite:sqlite" + ], + error_values=["", "\n"], + ) + def test_date_validation(self): self._run_field_validation( field=known_fields.DATE,