Ejemplo n.º 1
0
def create_tree(commits, head):
    try:
        repo = Repo('tree')
    except NoSuchPathError:
        repo = Repo.init('tree') # TODO Only use tree in dev-mode
        repo.init()

    index = repo.index
    delete_files()
    index.commit("Clearing index")  # Easiest way to clear the index is to commit an empty directory

    # Switch to temp first in case git-gud-construction exists
    if repo.head.reference.name != 'temp':
        repo.head.reference = Head(repo, 'refs/heads/temp')

    # Delete git-gud-construction so we can guarantee it's an orphan
    try:
        repo.delete_head('git-gud-construction')
    except GitCommandError:
        pass  # Branch doesn't exist

    repo.head.reference = Head(repo, 'refs/heads/git-gud-construction')
    try:
        repo.delete_head('temp')
    except GitCommandError:
        pass  # If temp didn't exist, we only checked it out as an orphan, so it already disappeared

    for branch in repo.branches:
        if branch.name != 'git-gud-construction':
            repo.delete_head(branch, force=True)
    repo.delete_tag(*repo.tags)

    index = repo.index
    commit_objects = {}

    for name, parents, branches, tags in commits:
        # commit = (name, parents, branches, tags)
        parents = [commit_objects[parent] for parent in parents]
        if parents:
            repo.active_branch.set_commit(parents[0])
        if len(parents) < 2:
            # Not a merge
            add_file_to_index(index, name)
        commit = index.commit(name, author=actor, committer=actor, parent_commits=parents)
        commit_objects[name] = commit

        for branch in branches:
            repo.create_head(branch, commit)

        for tag in tags:
            repo.create_tag(tag, commit)
        # TODO Log commit hash and info

    # TODO Checkout using name
    for branch in repo.branches:
        if branch.name == head:
            branch.checkout()

    repo.delete_head('git-gud-construction')
Ejemplo n.º 2
0
def get_repo(repo_name):
    directory = os.path.join(test_dir, repo_name)
    repo = Repo.init(directory)
    # Ensure the default branch is using a fixed name.
    # User config could change that,
    # breaking tests with implicit assumptions further down the line.
    repo.head.reference = Head(repo, 'refs/heads/master')

    # We need to synthesize the time stamps of commits to each be a second
    # apart, otherwise the commits may be at exactly the same second, which
    # means they won't always sort in order, and thus the merging of identical
    # metrics in adjacent commits may not happen correctly.
    base_time = time.time()

    base_path = os.path.join(base_dir, repo_name)
    for i in range(num_commits):
        files_dir = os.path.join(base_path, str(i))
        if not os.path.exists(files_dir):
            break

        files = os.listdir(files_dir)
        for filename in files:
            print("Copying file " + filename)
            path = os.path.join(base_path, str(i), filename)
            destination = os.path.join(directory, filename)
            shutil.copyfile(path, destination)

        repo.index.add("*")
        commit_date = datetime.datetime.fromtimestamp(base_time +
                                                      i).isoformat()
        commit_date = commit_date[:commit_date.find('.')]
        repo.index.commit("Commit {index}".format(index=i),
                          commit_date=commit_date)

    return directory
Ejemplo n.º 3
0
def checkout_branch(repo, branch_name, no_pull=False):
    """Checkout a branch and optionally pull updates.

    :param repo: Repo object
    :param branch_name: Name of the branch to checkout
    :param no_pull: (Default: False) If True, don't pull changes to branch

    :return: Head object for the checked out branch
    """
    base_head = Head(repo, f'refs/heads/{branch_name}')
    if repo.active_branch != base_head:
        print(f'Checking out {branch_name}.')
        base_head.checkout()
    if not no_pull and base_head.tracking_branch():
        print(f'Pulling updates to {branch_name}...')
        remote_name = base_head.tracking_branch().remote_name
        remote = Remote(repo, remote_name)
        base_commit = base_head.commit
        for fetch_info in remote.pull():
            if fetch_info.ref == base_head.tracking_branch():
                if fetch_info.commit != base_commit:
                    print(
                        f'Updated {branch_name} to {fetch_info.commit.hexsha}')
                else:
                    print(f'{branch_name} already up to date.')
        print('')
    return base_head
Ejemplo n.º 4
0
    def __init__(self,
                 git_object=None,
                 change_ids=list(),
                 upstream_branch=None,
                 force=False,
                 *args,
                 **kwargs):

        # make sure to correctly initialize inherited objects before performing
        # any computation
        super(Supersede, self).__init__(*args, **kwargs)

        # test commit parameter
        if not git_object:
            raise SupersedeError("Commit should be provided")

        # test that we can use this git repo
        if self.is_detached():
            raise SupersedeError("In 'detached HEAD' state")

        # To Do: check if it possible and useful.
        if self.repo.bare:
            raise SupersedeError("Cannot add notes in bare repositories")

        if not upstream_branch:
            raise SupersedeError("Missing upstream_branch parameter")

        try:
            # test commit "id" presence
            self._commit = self.repo.commit(git_object)
        except (BadName, BadObject):
            raise SupersedeError("Commit '%s' not found (or ambiguous)" %
                                 git_object)

        # test change_ids parameter
        if len(change_ids) == 0:
            raise SupersedeError("At least one change id should be provided")

        self._upstream_branch = upstream_branch
        self._change_ids = change_ids
        git_branch = Head(self.repo, 'refs/heads/%s' % upstream_branch)
        for change_id in change_ids:
            # Check change id format
            if not re.match(Supersede.CHANGE_ID_REGEX, change_id,
                            re.IGNORECASE):
                raise SupersedeError("Invalid Change Id '%s'" % change_id)

            # Check if change id is actually present in some commit
            # reachable from <upstream_branch>
            try:
                change_commit = CommitMessageSearcher(
                    repo=self.repo,
                    branch=git_branch,
                    pattern=Supersede.CHANGE_ID_HEADER_REGEX_FMT %
                    change_id).find()

                self.log.debug("Change-id '%s' found in commit '%s'" %
                               (change_id, change_commit))

            except RuntimeError:
                if force:
                    self.log.warn("Warning: change-id '%s' not found in '%s'" %
                                  (change_id, upstream_branch))
                else:
                    raise SupersedeError(
                        "Change-Id '%s' not found in branch '%s'" %
                        (change_id, upstream_branch))