Exemplo n.º 1
0
    def __get_notes_filename(cls, notes_rev):
        """Return the filename used to store the git notes.

        PARAMETERS
            notes_rev: The revision of the notes change.
        """
        # A git note for any given commit (called the "annotated commit"
        # in this function) is maintained through a file in the special
        # refs/notes/commits namespace.  The name of that file seems
        # to vary a little bit from case to case (sometimes it is just
        # equal to "%s" % rev, while some other times it is equal to
        # "%s/%s" % (rev[:2], rev[2:]) where rev is the revision of
        # the annotated commit. The one constant is that it is easy
        # to deduce the annotated commit ID, by just stripping the '/'
        # characters.

        # Look at the files modified by the git notes commit via
        # diff-tree. There should be only one, pointing us towards
        # the annotated commit.
        all_changes = diff_tree('-r', notes_rev)
        if not all_changes:
            # notes_rev is probably the root commit.  Just use the empty
            # tree's sha1 as the reference.
            empty_tree_rev = git.mktree(_input='')
            all_changes = diff_tree('-r', empty_tree_rev, notes_rev)

        # The output should be 2 lines...
        #   - The first line contains the hash of what is being compared,
        #     which should be notes_rev;
        #   - The second line contains the file change that interests us.
        # ... except in the case where the notes_rev does not have
        # a parent (first note).  In that case, we diff-tree'ed against
        # the empty tree rev, and the first line is omitted.
        #
        # Normally, there should only be one entry returned by diff_tree.
        # However, there is a situation where the output is more than
        # one entry: Newer version of git sometimes rename some of the
        # files created by older versions of "git notes" during notes
        # updates, and bunches those renamings together with a note
        # update, thus creating commits that actually touch multiple
        # files (N707-041). In that situation, it appears as though
        # the first entry is always the one corresponding to the commit
        # being annotated, so discard anything past the first line.
        assert all_changes

        (_, _, _, _, _, filename) = all_changes[0]
        return filename
Exemplo n.º 2
0
    def files_changed(self):
        """Return the list of files changed by this commit.

        Cache the result in self.__files_changed so that subsequent
        calls to this method do not require calling git again.
        """
        if self.__files_changed is None:
            self.__files_changed = []
            all_changes = diff_tree('-r', self.base_rev_for_git(), self.rev)
            for item in all_changes:
                (old_mode, new_mode, old_sha1, new_sha1, status, filename) \
                    = item
                debug('diff-tree entry: %s %s %s %s %s %s'
                      % (old_mode, new_mode, old_sha1, new_sha1, status,
                         filename),
                      level=5)
                self.__files_changed.append(filename)
        return self.__files_changed
Exemplo n.º 3
0
def style_check_commit(old_rev, new_rev, project_name):
    """Call check_file for every file changed between old_rev and new_rev.

    Raise InvalidUpdate if one or more style violation are detected.

    PARAMETERS
        old_rev: The commit to be used as a reference to determine
            the list of files that have been modified/added by
            the new commit.  Must be a valid revision.
        new_rev: The commit to be checked.
        project_name: The name of the project (same as the attribute
            in updates.emails.EmailInfo).
    """
    debug("style_check_commit(old_rev=%s, new_rev=%s)" % (old_rev, new_rev))

    # We allow users to explicitly disable pre-commit checks for
    # specific commits via the use of a special keyword placed anywhere
    # in the revision log. If found, then return immediately.
    raw_revlog = git.log("-1", new_rev, pretty="format:%B", _decode=True)
    if "no-precommit-check" in raw_revlog:
        debug("pre-commit checks explicity disabled for commit %s" % new_rev)
        return

    changes = diff_tree("-r", old_rev, new_rev)
    files_to_check = []

    for item in changes:
        (old_mode, new_mode, old_sha1, new_sha1, status, filename) = item
        debug(
            "diff-tree entry: %s %s %s %s %s %s" %
            (old_mode, new_mode, old_sha1, new_sha1, status, filename),
            level=5,
        )

        if status in ("D"):
            debug("deleted file ignored: %s" % filename, level=2)
        elif new_mode == "160000":
            debug("subproject entry ignored: %s" % filename, level=2)
        else:
            # Note: We treat a file rename as the equivalent of the old
            # file being deleted and the new file being added. This means
            # that we should run the pre-commit checks if applicable.
            # This is why we did not tell the `git diff-tree' command
            # above to detect renames, and why we do not have a special
            # branch for status values starting with `R'.
            files_to_check.append(filename)

    no_style_check_map = git_attribute(new_rev, files_to_check,
                                       "no-precommit-check")

    def needs_style_check_p(filename):
        """Return True if the file should be style-checked, False otherwise.

        In addition to returning True/False, it generates a debug log
        when the file does have a no-precommit-check attribute.
        """
        if no_style_check_map[filename] == "set":
            debug("no-precommit-check: %s commit_rev=%s" % (filename, new_rev))
            return False
        else:
            return True

    files_to_check = tuple(filter(needs_style_check_p, files_to_check))
    if not files_to_check:
        debug("style_check_commit: no files to style-check")
        return

    style_check_files(files_to_check, new_rev, project_name)