Пример #1
0
def commit_object():
    with seeded(17):
        # 20-byte sha1
        k = 20
        bits = random.getrandbits(k * 8)
        data = bits.to_bytes(k, sys.byteorder)  # in py39, can use randbytes(k)

        repo = None
        commit = git.Commit(repo, data)
        yield commit
Пример #2
0
    def _copy_commit(self, orig_commit, tree, parents):
        new_commit = git.Commit(
            self._repo, git.Commit.NULL_BIN_SHA, tree, orig_commit.author,
            orig_commit.authored_date, orig_commit.author_tz_offset,
            orig_commit.committer, orig_commit.committed_date,
            orig_commit.committer_tz_offset, "%s\n(sapling split of %s)" %
            (orig_commit.message, orig_commit.hexsha), parents,
            orig_commit.encoding)

        return self._write_commit(new_commit)
Пример #3
0
def test_collect_committers(user, expected):
    binsha = b'\x12' * 20
    commit = git.Commit('fake-repo', binsha,
                        author=user, committer=user,
                        message="fake commit message")
    dictresult = {'team-committers': [], 'team-committers-mails': [],
                  'external-committers': [], 'external-committers-mails': []}
    collect_committers(commit, dictresult,
                       {'*****@*****.**': '*****@*****.**',
                       })
    assert dictresult == expected
Пример #4
0
def commits_between(repo, start, stop):
    """
    Args:
        start (git.Commit): toplogically (chronologically) first commit
        stop (git.Commit): toplogically (chronologically) last commit

    Returns:
        list of git.Commit: between commits

    References:
        https://stackoverflow.com/questions/18679870/commits-between-2-hashes
        https://stackoverflow.com/questions/462974/diff-double-and-triple-dot

    Warning:
        this gets messy any node on the path between <start> and <stop> has
        more than one parent that is not on a path between <start> and <stop>

    Notes:
        As a prefix: the carrot (^A) removes commits reachable from A.
        As a suffix: the carrot (A^) references the 1st parent of A
        Furthermore:
            (A^n) references the n-th parent of A
            (A~n) references the n-th ancestor of A
            The tilde and carrot can be chained.
            A^^ = A~2 = the grandparent of A

        Reachable means everything in the past.

        PAST...............................PRESENT
        <p1> -- <start> -- <A> -- <B> -- <stop>
                /
        <p2> __/

    Example:
        >>> repo = git.Repo()
        >>> stop = repo.head.commit
        >>> start = stop.parents[0].parents[0].parents[0].parents[0]
        >>> commits = commits_between(repo, start, stop)
        >>> assert commits[0] == start
        >>> assert commits[-1] == stop
        >>> assert len(commits) == 4
    """
    import binascii
    argstr = '{start}^..{stop}'.format(start=start, stop=stop)
    hexshas = repo.git.rev_list(argstr).splitlines()
    binshas = [binascii.unhexlify(h) for h in hexshas]
    commits = [git.Commit(repo, b) for b in binshas]
    return commits
Пример #5
0
    def _raw_copy_commit(self, commit, message=None, parents=None, actor=None):
        warnings.warn("Will probable be removed with Git.merge_release_back().", PendingDeprecationWarning)
        # create a new commit reusing the tree (meaning no file changes)
        new_commit = git.Commit(self._get_local_repo(), git.Commit.NULL_BIN_SHA)
        new_commit.tree = commit.tree

        # set commit date
        unix_time = int(time())
        offset = altzone
        new_commit.authored_date = unix_time
        new_commit.author_tz_offset = offset
        # make sure we have a somewhat more linear history
        # (gitg and possibly others will get confused otherwise)
        if new_commit.authored_date == commit.authored_date:
            new_commit.authored_date = new_commit.authored_date + 1
        new_commit.committed_date = unix_time
        new_commit.committer_tz_offset = offset
        if new_commit.committed_date == commit.committed_date:
            new_commit.committed_date = new_commit.committed_date + 1

        # set author / comitter
        actor = self._get_release_actor(actor)
        new_commit.author = actor
        new_commit.committer = actor

        # set commit message
        if message:
            new_commit.message = message
        else:
            new_commit.message = commit.message

        # set parents
        new_commit.parents = parents if not parents is None else []

        # reuse encoding
        new_commit.encoding = commit.encoding
        return new_commit
Пример #6
0
 def ln_list_groups(self, groups):
     tags = self.ln_list_tags_commits()
     result = []
     for tag in tags:
         commits = dict()
         for item in tag['data']:
             for message in item.message.split('\n'):
                 for index in groups:
                     if index not in commits:
                         commits[index] = []
                     optional = re.findall(groups[index], message)
                     if optional:
                         commits[index].append(
                             dict(
                                 optional=optional[0],
                                 commit=git.Commit(
                                     item.repo,
                                     item.binsha,
                                     tree=item.tree,
                                     author=item.author,
                                     authored_date=item.authored_date,
                                     author_tz_offset=item.author_tz_offset,
                                     committer=item.committer,
                                     committed_date=item.committed_date,
                                     committer_tz_offset=item.
                                     committer_tz_offset,
                                     message=message.strip(),
                                     parents=item.parents,
                                     encoding=item.encoding,
                                     gpgsig=item.gpgsig)))
         for index in groups:
             if index in commits:
                 tag[index] = commits[index]
             else:
                 tag[index] = []
         result.append(tag)
     return result
Пример #7
0
    def _iter_commits_with_refs(self, *args, **kwargs):
        """
        A reimplementation of GitPython's iter_commits that includes
        the --decorate option.

        Unfortunately, iter_commits discards the additional info returned
        by adding --decorate, and the ref names are not exposed on the
        commit objects without making an entirely separate call to log.

        Ideally, since we're reimplementing it anyway, we would prefer
        to add all the info we need to the format to avoid the additional
        overhead of the lazy-load of the commit data, but the commit
        message is a problem since it can contain newlines which breaks
        parsing of the log lines (iter_commits can be broken this way,
        too).  This does keep the id_only case fast and the overhead
        of lazy-loading the commit data is probably fine.  But if this
        ends up being a bottleneck, that would be one possibile
        optimization.

        Renaming
        Detection of renaming can be implemented using diff with parent
        with create_path=True. But taking diffs is slow. That's why
        --name-status is added to log.
        Then log returns something like this:
            <commit hash>x00 <refs>
            \n # empty line
            R100 <renamed from path> <renamed to path> # when rename happens
            A\t<some path> # other cases
            D\t<some path> # other cases
            etc
        """
        proc = self._git.git.log(*args,
                                 format='%H%x00%d',
                                 as_process=True,
                                 **kwargs)
        stream = proc.stdout
        commit_lines = []
        while True:
            line = stream.readline()
            if '\x00' in line or not (len(line)):
                # hash line read, need to yield previous commit
                # first, cleaning lines a bit
                commit_lines = [
                    ln.strip('\n ').replace('\t', ' ') for ln in commit_lines
                    if ln.strip('\n ')
                ]
                if commit_lines:
                    hexsha, decoration = commit_lines[0].split('\x00')
                    if decoration:
                        # "->" replacement is because git 2.4 introduced "HEAD -> master" syntax
                        refs = decoration.strip(' ()').replace(
                            ' -> ', ', ').split(', ')
                    else:
                        refs = []
                    tag_prefix = 'tag: '  # introduced in git 1.8.3
                    for i, ref in enumerate(refs):
                        if ref.startswith(tag_prefix):
                            refs[i] = ref[len(tag_prefix):]
                    refs.sort()
                    renamed = {}
                    # merge commits don't have any --name-status output
                    if len(commit_lines) > 1:
                        name_stat_parts = commit_lines[1].split(' ')
                        if name_stat_parts[0] == 'R100':
                            renamed['from'] = name_stat_parts[1]
                            renamed['to'] = name_stat_parts[2]
                    yield (git.Commit(self._git,
                                      gitdb.util.hex_to_bin(hexsha)), refs,
                           renamed)
                if not (len(line)):
                    # if all lines have been read
                    break
                commit_lines = [line]
            else:
                commit_lines.append(line)
Пример #8
0
    if len(user_responses) == 1: continue
    time_categories = report['user_responses']['time_categories']
    #nasa_tlx = report['NASA-TLX']

    for category in time_categories:
        if 'refectoring' in category: break
    else:
        time_categories['refactoring'] = {u'time_spent': 0.0, u'difficulty': 0}
    #pp.pprint(log)
    total_time = (time_categories['planning']['time_spent'] +
                  time_categories['coding']['time_spent'] +
                  time_categories['refactoring']['time_spent'] +
                  time_categories['debugging']['time_spent'] +
                  time_categories['optimising']['time_spent'])
    total_time_per_commit.append(total_time)
    commit = git.Commit(repo, binascii.unhexlify(log[0]))
    lines_changed = 0
    print commit.diff(commit.parents[0])[0].diff
    diff = subprocess.check_output([
        "git", "--git-dir",
        os.path.join(args.repo_dir, ".git"), 'diff', commit.hexsha,
        commit.parents[0].hexsha
    ])
    sloc = 0
    for line in diff.split('\n'):
        if not (line.startswith("-") or line.startswith("+")): continue
        if line.strip() == "+" or line.strip() == "-": continue
        if line.startswith('+++') or line.startswith('---'): continue
        sloc += 1

    total_time_per_commit = sloc
Пример #9
0
#!/usr/bin/python
# -*- encoding: utf-8 -*-

import git
import sys
from collections import defaultdict
from textwrap import wrap
from email.Utils import formatdate

repo = git.Repo('.')
start = git.Commit(repo, sys.argv[1])
end = git.Commit(repo, 'HEAD')

curlog = repo.log(end)
oldlog = repo.log(start)

changelog = defaultdict(list)

for id in repo.commits_between(start, end):
    commit = git.Commit(repo, id)
    changelog[commit.author.name].append(commit.summary)

print 'bash-completion (X.Y)'
print

for author in sorted(changelog.keys()):
    print "  [ %s ]" % author
    for log in changelog[author]:
        print '\n'.join(
            wrap(log, initial_indent='  * ', subsequent_indent='    '))
    print