Exemple #1
0
class BodyRegexMatches(CommitRule):
    name = "body-match-regex"
    id = "B8"
    options_spec = [RegexOption('regex', None, "Regex the body should match")]

    def validate(self, commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        # We intentionally ignore the first line in the body as that's the empty line after the title,
        # which most users are not going to expect to be part of the body when matching a regex.
        # If this causes contention, we can always introduce an option to change the behavior in a backward-
        # compatible way.
        body_lines = commit.message.body[1:] if len(
            commit.message.body) > 1 else []

        # Similarly, the last line is often empty, this has to do with how git returns commit messages
        # User's won't expect this, so prune it off by default
        if body_lines and body_lines[-1] == "":
            body_lines.pop()

        full_body = "\n".join(body_lines)

        if not self.options['regex'].value.search(full_body):
            violation_msg = f"Body does not match regex ({self.options['regex'].value.pattern})"
            return [
                RuleViolation(self.id, violation_msg, None,
                              len(commit.message.body) + 1)
            ]
Exemple #2
0
class IgnoreByBody(ConfigurationRule):
    name = "ignore-by-body"
    id = "I2"
    options_spec = [
        RegexOption(
            'regex', None,
            "Regex matching lines of the body of commits this rule should apply to"
        ),
        StrOption('ignore', "all", "Comma-separated list of rules to ignore")
    ]

    def apply(self, config, commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        for line in commit.message.body:
            if self.options['regex'].value.match(line):
                config.ignore = self.options['ignore'].value

                message = f"Commit message line '{line}' matches the regex '{self.options['regex'].value.pattern}'," + \
                          f" ignoring rules: {self.options['ignore'].value}"

                self.log.debug("Ignoring commit because of rule '%s': %s",
                               self.id, message)
                # No need to check other lines if we found a match
                return
Exemple #3
0
class IgnoreByTitle(ConfigurationRule):
    name = "ignore-by-title"
    id = "I1"
    options_spec = [
        RegexOption(
            'regex', None,
            "Regex matching the titles of commits this rule should apply to"),
        StrOption('ignore', "all", "Comma-separated list of rules to ignore")
    ]

    def apply(self, config, commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        if self.options['regex'].value.match(commit.message.title):
            config.ignore = self.options['ignore'].value

            message = u"Commit title '{0}' matches the regex '{1}', ignoring rules: {2}"
            message = message.format(commit.message.title,
                                     self.options['regex'].value.pattern,
                                     self.options['ignore'].value)

            self.log.debug("Ignoring commit because of rule '%s': %s", self.id,
                           message)
Exemple #4
0
class AuthorValidEmail(CommitRule):
    name = "author-valid-email"
    id = "M1"
    options_spec = [RegexOption('regex', r"[^@ ]+@[^@ ]+\.[^@ ]+", "Regex that author email address should match")]

    def validate(self, commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        if commit.author_email and not self.options['regex'].value.match(commit.author_email):
            return [RuleViolation(self.id, "Author email for commit is invalid", commit.author_email)]
Exemple #5
0
class TitleRegexMatches(LineRule):
    name = "title-match-regex"
    id = "T7"
    target = CommitMessageTitle
    options_spec = [RegexOption('regex', None, "Regex the title should match")]

    def validate(self, title, _commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        if not self.options['regex'].value.search(title):
            violation_msg = f"Title does not match regex ({self.options['regex'].value.pattern})"
            return [RuleViolation(self.id, violation_msg, title)]
Exemple #6
0
class IgnoreBodyLines(ConfigurationRule):
    name = "ignore-body-lines"
    id = "I3"
    options_spec = [RegexOption('regex', None, "Regex matching lines of the body that should be ignored")]

    def apply(self, _, commit):
        # If no regex is specified, immediately return
        if not self.options['regex'].value:
            return

        new_body = []
        for line in commit.message.body:
            if self.options['regex'].value.match(line):
                debug_msg = "Ignoring line '%s' because it matches '%s'"
                self.log.debug(debug_msg, line, self.options['regex'].value.pattern)
            else:
                new_body.append(line)

        commit.message.body = new_body
        commit.message.full = "\n".join([commit.message.title] + new_body)
Exemple #7
0
    def test_regex_option(self):
        # normal behavior
        option = RegexOption(u"tëst-regex", u"^myrëgex(.*)foo$",
                             u"Tëst Regex Description")
        self.assertEqual(option.name, u"tëst-regex")
        self.assertEqual(option.description, u"Tëst Regex Description")
        self.assertEqual(option.value,
                         re.compile(u"^myrëgex(.*)foo$", re.UNICODE))

        # re-set value
        option.set(u"[0-9]föbar.*")
        self.assertEqual(option.value, re.compile(u"[0-9]föbar.*", re.UNICODE))

        # set None
        option.set(None)
        self.assertIsNone(option.value)

        # error on invalid regex
        incorrect_values = [u"foo(", 123, -1]
        for value in incorrect_values:
            with self.assertRaisesRegex(RuleOptionError,
                                        u"Invalid regular expression"):
                option.set(value)