Пример #1
0
	def commit(self, message, parent_commits=None, head=True):
		"""Commit the current default index file, creating a commit object.

		For more information on the arguments, see tree.commit.
		:note:
			If you have manually altered the .entries member of this instance,
			don't forget to write() your changes to disk beforehand.

		:return:
			Commit object representing the new commit"""
		tree = self.write_tree()
		return Commit.create_from_tree(self.repo, tree, message, parent_commits, head)
Пример #2
0
	def commit(self, message, parent_commits=None, head=True):
		"""Commit the current default index file, creating a commit object.

		For more information on the arguments, see tree.commit.
		:note:
			If you have manually altered the .entries member of this instance,
			don't forget to write() your changes to disk beforehand.

		:return:
			Commit object representing the new commit"""
		tree = self.write_tree()
		return Commit.create_from_tree(self.repo, tree, message, parent_commits, head)
Пример #3
0
def commit_from_binsha(repo, binsha, org_commit, parents=None):
    message = org_commit.message.encode(org_commit.encoding)

    tree = Tree.new(repo, bin_to_hex(binsha))

    new_commit = Commit(repo, Commit.NULL_BIN_SHA, tree,
                        org_commit.author, org_commit.authored_date, org_commit.author_tz_offset,
                        org_commit.committer, org_commit.committed_date, org_commit.committer_tz_offset,
                        message, parents, org_commit.encoding)
    stream = StringIO()
    new_commit._serialize(stream)
    streamlen = stream.tell()
    stream.seek(0)
    istream = repo.odb.store(IStream(Commit.type, streamlen, stream))
    new_commit.binsha = istream.binsha

    try:
        repo.head.set_commit(new_commit, logmsg="commit: %s" % message)
    except ValueError:
        master = git.refs.Head.create(repo, repo.head.ref, new_commit, logmsg="commit (initial): %s" % message)
        repo.head.set_reference(master, logmsg='commit: Switching to %s' % master)

    return new_commit
Пример #4
0
    def commit(self, message, parent_commits=None, head=True, author=None,
               committer=None, author_date=None, commit_date=None):
        """Commit the current default index file, creating a commit object.
        For more information on the arguments, see tree.commit.

        :note: If you have manually altered the .entries member of this instance,
               don't forget to write() your changes to disk beforehand.
        :return: Commit object representing the new commit"""
        run_commit_hook('pre-commit', self)
        tree = self.write_tree()
        rval = Commit.create_from_tree(self.repo, tree, message, parent_commits,
                                       head, author=author, committer=committer,
                                       author_date=author_date, commit_date=commit_date)
        run_commit_hook('post-commit', self)
        return rval
Пример #5
0
def commit_from_binsha(repo, binsha, org_commit, parents=None):
    tree = Tree.new(repo, bin_to_hex(binsha))

    env = os.environ

    offset = altz_to_utctz_str(org_commit.author_tz_offset)
    date = org_commit.authored_date
    env[Commit.env_author_date] = '{} {}'.format(date, offset)

    offset = altz_to_utctz_str(org_commit.committer_tz_offset)
    date = org_commit.committed_date
    env[Commit.env_committer_date] = '{} {}'.format(date, offset)

    return Commit.create_from_tree(repo, tree, org_commit.message, parents,
                                   head=True,
                                   author=org_commit.author,
                                   committer=org_commit.committer)
Пример #6
0
def commit_from_binsha(repo, binsha, org_commit, parents=None):
    env = os.environ

    author_date = "%d %s" % (org_commit.authored_date, altz_to_utctz_str(org_commit.author_tz_offset))
    env[Commit.env_author_date] = author_date

    committer_date = "%d %s" % (org_commit.committed_date, altz_to_utctz_str(org_commit.committer_tz_offset))
    env[Commit.env_committer_date] = committer_date

    env[Actor.env_author_name] = org_commit.author.name.encode(org_commit.encoding)
    env[Actor.env_author_email] = org_commit.author.email or ""

    env[Actor.env_committer_name] = org_commit.committer.name.encode(org_commit.encoding)
    env[Actor.env_committer_email] = org_commit.committer.email or ""

    message = org_commit.message.encode(org_commit.encoding)

    tree = Tree.new(repo, bin_to_hex(binsha))

    return Commit.create_from_tree(repo, tree, message, parents, True)
Пример #7
0
    def iter_commits(self, rev=None, paths='', **kwargs):
        """A list of Commit objects representing the history of a given ref/commit

        :parm rev:
            revision specifier, see git-rev-parse for viable options.
            If None, the active branch will be used.

        :parm paths:
            is an optional path or a list of paths to limit the returned commits to
            Commits that do not contain that path or the paths will not be returned.

        :parm kwargs:
            Arguments to be passed to git-rev-list - common ones are
            max_count and skip

        :note: to receive only commits between two named revisions, use the
            "revA...revB" revision specifier

        :return ``git.Commit[]``"""
        if rev is None:
            rev = self.head.commit

        return Commit.iter_items(self, rev, paths, **kwargs)
Пример #8
0
    def iter_commits(self, rev=None, paths='', **kwargs):
        """A list of Commit objects representing the history of a given ref/commit

        :parm rev:
            revision specifier, see git-rev-parse for viable options.
            If None, the active branch will be used.

        :parm paths:
            is an optional path or a list of paths to limit the returned commits to
            Commits that do not contain that path or the paths will not be returned.

        :parm kwargs:
            Arguments to be passed to git-rev-list - common ones are
            max_count and skip

        :note: to receive only commits between two named revisions, use the
            "revA...revB" revision specifier

        :return ``git.Commit[]``"""
        if rev is None:
            rev = self.head.commit

        return Commit.iter_items(self, rev, paths, **kwargs)
Пример #9
0
    def blame(self, rev, file):
        """The blame information for the given file at the given revision.

        :parm rev: revision specifier, see git-rev-parse for viable options.
        :return:
            list: [git.Commit, list: [<line>]]
            A list of tuples associating a Commit object with a list of lines that
            changed within the given commit. The Commit objects will be given in order
            of appearance."""
        data = self.git.blame(rev, '--', file, p=True, stdout_as_string=False)
        commits = dict()
        blames = list()
        info = None

        keepends = True
        for line in data.splitlines(keepends):
            try:
                line = line.rstrip().decode(defenc)
            except UnicodeDecodeError:
                firstpart = ''
                is_binary = True
            else:
                # As we don't have an idea when the binary data ends, as it could contain multiple newlines
                # in the process. So we rely on being able to decode to tell us what is is.
                # This can absolutely fail even on text files, but even if it does, we should be fine treating it
                # as binary instead
                parts = self.re_whitespace.split(line, 1)
                firstpart = parts[0]
                is_binary = False
            # end handle decode of line

            if self.re_hexsha_only.search(firstpart):
                # handles
                # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7        - indicates blame-data start
                # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2          - indicates
                # another line of blame with the same data
                digits = parts[-1].split(" ")
                if len(digits) == 3:
                    info = {'id': firstpart}
                    blames.append([None, []])
                elif info['id'] != firstpart:
                    info = {'id': firstpart}
                    blames.append([commits.get(firstpart), []])
                # END blame data initialization
            else:
                m = self.re_author_committer_start.search(firstpart)
                if m:
                    # handles:
                    # author Tom Preston-Werner
                    # author-mail <*****@*****.**>
                    # author-time 1192271832
                    # author-tz -0700
                    # committer Tom Preston-Werner
                    # committer-mail <*****@*****.**>
                    # committer-time 1192271832
                    # committer-tz -0700  - IGNORED BY US
                    role = m.group(0)
                    if firstpart.endswith('-mail'):
                        info["%s_email" % role] = parts[-1]
                    elif firstpart.endswith('-time'):
                        info["%s_date" % role] = int(parts[-1])
                    elif role == firstpart:
                        info[role] = parts[-1]
                    # END distinguish mail,time,name
                else:
                    # handle
                    # filename lib/grit.rb
                    # summary add Blob
                    # <and rest>
                    if firstpart.startswith('filename'):
                        info['filename'] = parts[-1]
                    elif firstpart.startswith('summary'):
                        info['summary'] = parts[-1]
                    elif firstpart == '':
                        if info:
                            sha = info['id']
                            c = commits.get(sha)
                            if c is None:
                                c = Commit(
                                    self,
                                    hex_to_bin(sha),
                                    author=Actor._from_string(
                                        info['author'] + ' ' +
                                        info['author_email']),
                                    authored_date=info['author_date'],
                                    committer=Actor._from_string(
                                        info['committer'] + ' ' +
                                        info['committer_email']),
                                    committed_date=info['committer_date'],
                                    message=info['summary'])
                                commits[sha] = c
                            # END if commit objects needs initial creation
                            if not is_binary:
                                if line and line[0] == '\t':
                                    line = line[1:]
                            else:
                                # NOTE: We are actually parsing lines out of binary data, which can lead to the
                                # binary being split up along the newline separator. We will append this to the blame
                                # we are currently looking at, even though it should be concatenated with the last line
                                # we have seen.
                                pass
                            # end handle line contents
                            blames[-1][0] = c
                            blames[-1][1].append(line)
                            info = {'id': sha}
                        # END if we collected commit info
                    # END distinguish filename,summary,rest
                # END distinguish author|committer vs filename,summary,rest
            # END distinguish hexsha vs other information
        return blames
Пример #10
0
    def blame_incremental(self, rev, file, **kwargs):
        """Iterator for blame information for the given file at the given revision.

        Unlike .blame(), this does not return the actual file's contents, only
        a stream of BlameEntry tuples.

        :parm rev: revision specifier, see git-rev-parse for viable options.
        :return: lazy iterator of BlameEntry tuples, where the commit
                 indicates the commit to blame for the line, and range
                 indicates a span of line numbers in the resulting file.

        If you combine all line number ranges outputted by this command, you
        should get a continuous range spanning all line numbers in the file.
        """
        data = self.git.blame(rev,
                              '--',
                              file,
                              p=True,
                              incremental=True,
                              stdout_as_string=False,
                              **kwargs)
        commits = dict()

        stream = (line for line in data.split(b'\n') if line)
        while True:
            line = next(
                stream
            )  # when exhausted, causes a StopIteration, terminating this function
            hexsha, orig_lineno, lineno, num_lines = line.split()
            lineno = int(lineno)
            num_lines = int(num_lines)
            orig_lineno = int(orig_lineno)
            if hexsha not in commits:
                # Now read the next few lines and build up a dict of properties
                # for this commit
                props = dict()
                while True:
                    line = next(stream)
                    if line == b'boundary':
                        # "boundary" indicates a root commit and occurs
                        # instead of the "previous" tag
                        continue

                    tag, value = line.split(b' ', 1)
                    props[tag] = value
                    if tag == b'filename':
                        # "filename" formally terminates the entry for --incremental
                        orig_filename = value
                        break

                c = Commit(
                    self,
                    hex_to_bin(hexsha),
                    author=Actor(
                        safe_decode(props[b'author']),
                        safe_decode(
                            props[b'author-mail'].lstrip(b'<').rstrip(b'>'))),
                    authored_date=int(props[b'author-time']),
                    committer=Actor(
                        safe_decode(props[b'committer']),
                        safe_decode(props[b'committer-mail'].lstrip(
                            b'<').rstrip(b'>'))),
                    committed_date=int(props[b'committer-time']))
                commits[hexsha] = c
            else:
                # Discard all lines until we find "filename" which is
                # guaranteed to be the last line
                while True:
                    line = next(
                        stream)  # will fail if we reach the EOF unexpectedly
                    tag, value = line.split(b' ', 1)
                    if tag == b'filename':
                        orig_filename = value
                        break

            yield BlameEntry(commits[hexsha], range(lineno,
                                                    lineno + num_lines),
                             safe_decode(orig_filename),
                             range(orig_lineno, orig_lineno + num_lines))
Пример #11
0
    def blame_incremental(self, rev, file, **kwargs):
        """Iterator for blame information for the given file at the given revision.

        Unlike .blame(), this does not return the actual file's contents, only
        a stream of (commit, range) tuples.

        :parm rev: revision specifier, see git-rev-parse for viable options.
        :return: lazy iterator of (git.Commit, range) tuples, where the commit
                 indicates the commit to blame for the line, and range
                 indicates a span of line numbers in the resulting file.

        If you combine all line number ranges outputted by this command, you
        should get a continuous range spanning all line numbers in the file.
        """
        data = self.git.blame(rev,
                              '--',
                              file,
                              p=True,
                              incremental=True,
                              stdout_as_string=False,
                              **kwargs)
        commits = dict()

        stream = iter(data.splitlines())
        while True:
            line = next(
                stream
            )  # when exhausted, casues a StopIteration, terminating this function

            hexsha, _, lineno, num_lines = line.split()
            lineno = int(lineno)
            num_lines = int(num_lines)
            if hexsha not in commits:
                # Now read the next few lines and build up a dict of properties
                # for this commit
                props = dict()
                while True:
                    line = next(stream)
                    if line == b'boundary':
                        # "boundary" indicates a root commit and occurs
                        # instead of the "previous" tag
                        continue

                    tag, value = line.split(b' ', 1)
                    props[tag] = value
                    if tag == b'filename':
                        # "filename" formally terminates the entry for --incremental
                        break

                c = Commit(
                    self,
                    hex_to_bin(hexsha),
                    author=Actor(
                        safe_decode(props[b'author']),
                        safe_decode(
                            props[b'author-mail'].lstrip(b'<').rstrip(b'>'))),
                    authored_date=int(props[b'author-time']),
                    committer=Actor(
                        safe_decode(props[b'committer']),
                        safe_decode(props[b'committer-mail'].lstrip(
                            b'<').rstrip(b'>'))),
                    committed_date=int(props[b'committer-time']),
                    message=safe_decode(props[b'summary']))
                commits[hexsha] = c
            else:
                # Discard the next line (it's a filename end tag)
                line = next(stream)
                assert line.startswith(
                    b'filename'), 'Unexpected git blame output'

            yield commits[hexsha], range(lineno, lineno + num_lines)
Пример #12
0
        path = "jEdit"
        url = "/Users/kenjif/msr_repos/git/jEdit"
        write_submodule_config(f, name, path, url)

    committed = {}
    tags = {}
    heads = {}
    for tag_ref in repo.tags:
        tags[tag_ref.commit.hexsha] = tag_ref.name

    for head in repo.heads:
        heads[head.commit.hexsha] = head.name

    for commit_hexsha, num in izip(commits, count()):
        print num, commit_hexsha
        git = new_repo.git
        commit = repo.commit(commit_hexsha)

        parents = []
        for parent in commit.parents:
            parents.append(committed[parent.hexsha])

        message = "[%s] from %s" % (num, commit_hexsha)
        new_tree = create_submodule_tree(new_repo.odb, commit_hexsha)
        new_commit = Commit.create_from_tree(new_repo, new_tree, message, parents)
        if commit_hexsha in tags:
            new_repo.create_tag(tags[commit_hexsha], ref=new_commit)
        if commit_hexsha in heads:
            new_repo.create_head(heads[commit_hexsha], commit=new_commit)
        committed[commit_hexsha] = new_commit
Пример #13
0
        children = []
        for parent in commit.parents:
            if parent.hexsha not in visited:
                children.append(parent.hexsha)

        if children:
            nodes.extend(children)
        else:
            nodes.pop()
            visited.add(node)
            post.append(node)

    return post


if __name__ == '__main__':
    repo = Repo.init('test_git')
    # (mode, binsha) = write_tree(repo.odb, 'temp')

    # (mode, binsha) = write_tree(repo.odb, 'temp/00')
    # (mode, binsha) = write_tree(repo.odb, 'temp/01')

    paths = ['temp/00', 'temp/01']
    names = ['a', 'b']

    (mode, binsha) = write_paths(repo.odb, paths, names)

    tree = Tree.new(repo, bin_to_hex(binsha))
    c = Commit.create_from_tree(repo, tree, 'test commit', None, True)