|
@@ -366,3 +366,76 @@ class VariableWithBraces(_CheckFunction):
|
|
|
return ["{}:{}: use $() to delimit variables, not ${{}}"
|
|
|
.format(self.filename, lineno),
|
|
|
text]
|
|
|
+
|
|
|
+
|
|
|
+class CPEVariables(_CheckFunction):
|
|
|
+ """
|
|
|
+ Check that the values for the CPE variables are not the default.
|
|
|
+ - CPE_ID_* variables must not be set to their default
|
|
|
+ - CPE_ID_VALID must not be set if a non-default CPE_ID variable is set
|
|
|
+ """
|
|
|
+ def before(self):
|
|
|
+ pkg, _ = os.path.splitext(os.path.basename(self.filename))
|
|
|
+ self.CPE_fields_defaults = {
|
|
|
+ "VALID": "NO",
|
|
|
+ "PREFIX": "cpe:2.3:a",
|
|
|
+ "VENDOR": f"{pkg}_project",
|
|
|
+ "PRODUCT": pkg,
|
|
|
+ "VERSION": None,
|
|
|
+ "UPDATE": "*",
|
|
|
+ }
|
|
|
+ self.valid = None
|
|
|
+ self.non_defaults = 0
|
|
|
+ self.CPE_FIELDS_RE = re.compile(
|
|
|
+ r"^\s*(.+_CPE_ID_({}))\s*=\s*(.+)$"
|
|
|
+ .format("|".join(self.CPE_fields_defaults)),
|
|
|
+ )
|
|
|
+ self.VERSION_RE = re.compile(
|
|
|
+ rf"^(HOST_)?{pkg.upper().replace('-', '_')}_VERSION\s*=\s*(.+)$",
|
|
|
+ )
|
|
|
+ self.COMMENT_RE = re.compile(r"^\s*#.*")
|
|
|
+
|
|
|
+ def check_line(self, lineno, text):
|
|
|
+ text = self.COMMENT_RE.sub('', text.rstrip())
|
|
|
+
|
|
|
+ # WARNING! The VERSION_RE can _also_ match the same lines as CPE_FIELDS_RE,
|
|
|
+ # but not the other way around. So we must first check for CPE_FIELDS_RE,
|
|
|
+ # and if not matched, then and only then check for VERSION_RE.
|
|
|
+ match = self.CPE_FIELDS_RE.match(text)
|
|
|
+ if match:
|
|
|
+ var, field, val = match.groups()
|
|
|
+ return self._check_field(lineno, text, field, var, val)
|
|
|
+
|
|
|
+ match = self.VERSION_RE.match(text)
|
|
|
+ if match:
|
|
|
+ self.CPE_fields_defaults["VERSION"] = match.groups()[1]
|
|
|
+
|
|
|
+ def after(self):
|
|
|
+ # "VALID" counts in the non-defaults; so when "VALID" is present,
|
|
|
+ # 1 non-default means only "VALID" is present, so that's OK.
|
|
|
+ if self.valid and self.non_defaults > 1:
|
|
|
+ return ["{}:{}: 'YES' is implied when a non-default CPE_ID field is specified: {} ({}#cpe-id)".format(
|
|
|
+ self.filename,
|
|
|
+ self.valid["lineno"],
|
|
|
+ self.valid["text"],
|
|
|
+ self.url_to_manual,
|
|
|
+ )]
|
|
|
+
|
|
|
+ def _check_field(self, lineno, text, field, var, val):
|
|
|
+ if field == "VERSION" and self.CPE_fields_defaults[field] is None:
|
|
|
+ return ["{}:{}: expecting package version to be set before CPE_ID_VERSION".format(
|
|
|
+ self.filename,
|
|
|
+ lineno,
|
|
|
+ )]
|
|
|
+ if val == self.CPE_fields_defaults[field]:
|
|
|
+ return ["{}:{}: '{}' is the default value for {} ({}#cpe-id)".format(
|
|
|
+ self.filename,
|
|
|
+ lineno,
|
|
|
+ val,
|
|
|
+ var,
|
|
|
+ self.url_to_manual,
|
|
|
+ )]
|
|
|
+ else:
|
|
|
+ if field == "VALID":
|
|
|
+ self.valid = {"lineno": lineno, "text": text}
|
|
|
+ self.non_defaults += 1
|