Beispiel #1
0
    def process_new_dependency(self,dependent, dependent_sha1,
                               dependency, dependency_sha1,
                               path, line_num):
        if not self.seen_commit(dependency):
            self.notify_listeners("new_commit", dependency)
            self.dependencies[dependent_sha1][dependency_sha1] = {}

        self.notify_listeners("new_dependency",
                              dependent, dependency, path, line_num)

        self.logger.info(
            "          New dependency %s -> %s via line %s (%s)" %
            (dependent_sha1[:8], dependency_sha1[:8], line_num,
             GitUtils.oneline(dependency)))

        if dependency_sha1 in self.todo_d:
            self.logger.info(
                "        Dependency on %s via line %s already in TODO"
                % (dependency_sha1[:8], line_num,))
            return

        if dependency_sha1 in self.done_d:
            self.logger.info(
                "        Dependency on %s via line %s already done" %
                (dependency_sha1[:8], line_num,))
            return

        if dependency_sha1 not in self.dependencies:
            if self.options.recurse:
                self.todo.append(dependency)
                self.todo_d[dependency.hex] = True
                self.logger.info("  + Added %s to TODO" %
                                  dependency.hex[:8])
Beispiel #2
0
    def process_hunk_line(self, dependent, dependent_sha1, parent,
                          path, line, line_to_culprit):
        self.logger.debug("          ! " + line.rstrip())
        m = re.match('^([0-9a-f]{40}) (\d+) (\d+)( \d+)?$', line)
        if not m:
            return

        dependency_sha1, orig_line_num, line_num = m.group(1, 2, 3)
        line_num = int(line_num)
        dependency = self.get_commit(dependency_sha1)
        line_to_culprit[line_num] = dependency.hex

        if self.is_excluded(dependency):
            self.logger.debug(
                "          Excluding dependency %s from line %s (%s)" %
                (dependency_sha1[:8], line_num,
                 GitUtils.oneline(dependency)))
            return

        if dependency_sha1 not in self.dependencies[dependent_sha1]:
            self.process_new_dependency(dependent, dependent_sha1,
                                        dependency, dependency_sha1,
                                        path, line_num)

        self.record_dependency_source(parent,
                                      dependent, dependent_sha1,
                                      dependency, dependency_sha1,
                                      path, line_num, line)
Beispiel #3
0
 def cherry_pick(self, sha):
     GitExplodeUtils.git('cherry-pick', sha)
     self.update_current_topic(sha)
     head = GitExplodeUtils.get_head_sha1()
     self.exploded[sha] = head
     commit = GitUtils.ref_commit(self.repo, sha)
     self.logger.debug(
         "- cherry-picked %s as %s (%s)" %
         (sha[:8], self.exploded[sha][:8], GitUtils.oneline(commit)))
Beispiel #4
0
    def blame_hunk(self, dependent, parent, path, hunk):
        """Run git blame on the parts of the hunk which exist in the older
        commit in the diff.  The commits generated by git blame are
        the commits which the newer commit in the diff depends on,
        because without the lines from those commits, the hunk would
        not apply correctly.
        """
        line_range_before = "-%d,%d" % (hunk.old_start, hunk.old_lines)
        line_range_after = "+%d,%d" % (hunk.new_start, hunk.new_lines)
        self.logger.debug("        Blaming hunk %s @ %s" %
                          (line_range_before, parent.hex[:8]))

        if not self.tree_lookup(path, parent):
            # This is probably because dependent added a new directory
            # which was not previously in the parent.
            return

        cmd = [
            'git', 'blame', '--porcelain', '-L',
            "%d,+%d" % (hunk.old_start, hunk.old_lines), parent.hex, '--', path
        ]
        blame = subprocess.check_output(cmd, universal_newlines=True)

        dependent_sha1 = dependent.hex
        if dependent_sha1 not in self.dependencies:
            self.logger.debug("          New dependent: %s" %
                              GitUtils.commit_summary(dependent))
            self.dependencies[dependent_sha1] = {}
            self.notify_listeners("new_dependent", dependent)

        line_to_culprit = {}

        for line in blame.split('\n'):
            self.logger.debug("        !" + line.rstrip())
            m = re.match('^([0-9a-f]{40}) (\d+) (\d+)( \d+)?$', line)
            if not m:
                continue
            dependency_sha1, orig_line_num, line_num = m.group(1, 2, 3)
            line_num = int(line_num)
            dependency = self.get_commit(dependency_sha1)
            line_to_culprit[line_num] = dependency.hex

            if self.is_excluded(dependency):
                self.logger.debug(
                    "        Excluding dependency %s from line %s (%s)" %
                    (dependency_sha1[:8], line_num,
                     GitUtils.oneline(dependency)))
                continue

            if dependency_sha1 not in self.dependencies[dependent_sha1]:
                if not self.seen_commit(dependency):
                    self.notify_listeners("new_commit", dependency)
                    self.dependencies[dependent_sha1][dependency_sha1] = {}

                self.notify_listeners("new_dependency", dependent, dependency,
                                      path, line_num)

                self.logger.debug(
                    "          New dependency %s -> %s via line %s (%s)" %
                    (dependent_sha1[:8], dependency_sha1[:8], line_num,
                     GitUtils.oneline(dependency)))

                if dependency_sha1 in self.todo_d:
                    self.logger.debug(
                        "        Dependency on %s via line %s already in TODO"
                        % (
                            dependency_sha1[:8],
                            line_num,
                        ))
                    continue

                if dependency_sha1 in self.done_d:
                    self.logger.debug(
                        "        Dependency on %s via line %s already done" % (
                            dependency_sha1[:8],
                            line_num,
                        ))
                    continue

                if dependency_sha1 not in self.dependencies:
                    if self.options.recurse:
                        self.todo.append(dependency)
                        self.todo_d[dependency.hex] = True
                        self.logger.debug("  + Added %s to TODO" %
                                          dependency.hex[:8])

            dep_sources = self.dependencies[dependent_sha1][dependency_sha1]

            if path not in dep_sources:
                dep_sources[path] = {}
                self.notify_listeners('new_path', dependent, dependency, path,
                                      line_num)

            if line_num in dep_sources[path]:
                abort("line %d already found when blaming %s:%s\n"
                      "old:\n  %s\n"
                      "new:\n  %s" % (line_num, parent.hex[:8], path,
                                      dep_sources[path][line_num], line))

            dep_sources[path][line_num] = line
            self.logger.debug("          New line for %s -> %s: %s" %
                              (dependent_sha1[:8], dependency_sha1[:8], line))
            self.notify_listeners('new_line', dependent, dependency, path,
                                  line_num)

        diff_format = '      |%8.8s %5s %s%s'
        hunk_header = '@@ %s %s @@' % (line_range_before, line_range_after)
        self.logger.debug(diff_format % ('--------', '-----', '', hunk_header))
        line_num = hunk.old_start
        for line in hunk.lines:
            if "\n\\ No newline at end of file" == line.content.rstrip():
                break
            if line.origin == '+':
                rev = ln = ''
            else:
                rev = line_to_culprit[line_num]
                ln = line_num
                line_num += 1
            self.logger.debug(diff_format %
                              (rev, ln, line.origin, line.content.rstrip()))