Example #1
0
    def _parse_line(self, line):
        if not line:
            if self.commit is None:
                return

            if self.rev_separator is not None:
                self.rev_separator += '\n'
            elif self.file_separator is not None:
                self.file_separator += '\n'
            elif self.commit.message is not None:
                self.commit.message += '\n'

            return

        # Revision Separator
        if self.patterns['rev-separator'].match(line):
            # Ignore separators so that we don't
            # include it in the commit message
            if self.rev_separator is None:
                self.rev_separator = line
            else:
                self.rev_separator += line + '\n'

            return

        # File Separator
        if self.patterns['file-separator'].match(line):
            # Ignore separators so that we don't
            # include it in the commit message
            if self.file_separator is None:
                self.file_separator = line
            else:
                self.file_separator += line + '\n'

            return

            # File
        match = self.patterns['file'].match(line)
        if match:
            self.flush()

            path = match.group(1)
            path = path[len(self.root_path):]
            path = path[:path.rfind(',')]

            self.file = path

            self.branches = {}
            self.tags = {}
            self.commit = None
            self.file_separator = None

            return

        # Branch
        match = self.patterns['branch'].match(line)
        if match:
            self.branches[match.group(2) + match.group(4)] = match.group(1)

            return

        # Tag (Keep this always after Branch pattern)
        match = self.patterns['tag'].match(line)
        if match:
            revision = match.group(2)

            # We are ignoring 1.1.1.1 revisions,
            # so in case there's a tag pointing to that
            # revision we have to redirect it to 1.1 revision
            if revision == '1.1.1.1':
                revision = '1.1'

            self.tags.setdefault(revision, []).append(match.group(1))

            return

        # Revision
        match = self.patterns['revision'].match(line)
        if match and self.rev_separator is not None:
            self._handle_commit()

            revision = match.group(1)

            commit = Commit()
            # composed rev: revision + | + file path
            # to make sure revision is unique
            commit.composed_rev = True
            commit.revision = "%s|%s" % (revision, self.file)
            commit.tags = self.tags.get(revision, None)
            self.commit = commit

            self.rev_separator = None

            return

        # Commit info (date, author, etc.)
        match = self.patterns['info'].match(line)
        if match and self.commit is not None:
            commit = self.commit

            revision = commit.revision.split('|')[0]
            if revision == '1.1.1.1':
                self.commit = None
                return

            commit.committer = Person()
            commit.committer.name = match.group(8)
            self.handler.committer(commit.committer)

            commit.date = datetime.datetime(int(match.group(1)), int(match.group(2)), int(match.group(3)),
                                            int(match.group(4)), int(match.group(5)), int(match.group(6)))

            if match.group(10) is not None:
                self.lines[commit.revision] = (int(match.group(11)), int(match.group(12)))
            else:
                self.lines[commit.revision] = (0, 0)

            action = Action()
            act = match.group(9)
            if act == 'dead':
                action.type = 'D'
                self.file = self.file.replace('/Attic', '')
                commit.revision = commit.revision.replace('/Attic', '')
            elif revision == '1.1':
                action.type = 'A'
            else:
                action.type = 'M'
            action.f1 = self.file

            # Branch
            try:
                last_dot = revision.rfind('.')
                prefix = revision[:last_dot]
                branch = self.branches[prefix]
                if self.file_added_on_branch and \
                        self.file_added_on_branch == prefix and \
                        revision[last_dot + 1:] == '1':
                    action.type = 'A'
                    self.file_added_on_branch = None

            except KeyError:
                branch = 'trunk'

            commit.branch = branch

            commit.actions.append(action)

            return

        # Branches
        match = self.patterns['branches'].match(line)
        if match:
            if self.commit is None:
                return

            action = self.commit.actions[0]
            revision = self.commit.revision.split('|')[0]
            if action.type == 'D' and revision == '1.1':
                # File added on a branch
                self.file_added_on_branch = match.group(1)

                # Discard this commit
                self.commit = None

            return

        # Message.
        if self.commit is not None:
            if self.rev_separator is not None:
                # Previous separator was probably a
                # false positive
                self.commit.message += self.rev_separator + '\n'
                self.rev_separator = None
            if self.file_separator is not None:
                # Previous separator was probably a
                # false positive
                self.commit.message += self.file_separator + '\n'
                self.file_separator = None
            self.commit.message += line + '\n'