Exemplo n.º 1
0
    def test_diff_pull_request(self):
        """ Test pagure.lib.git.diff_pull_request """
        gitrepo = os.path.join(self.path, 'repos', 'test.git')
        gitrepo2 = os.path.join(self.path, 'repos', 'forks', 'pingou',
                                'test.git')
        request = pagure.lib.query.search_pull_requests(self.session,
                                                        requestid=1,
                                                        project_id=1)

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            with_diff=True)

        self.assertEqual(len(diff_commits), 2)
        self.assertEqual(
            diff_commits[0].message,
            'Second edit on side branch of the file sources for testing')
        self.assertEqual(
            diff_commits[1].message,
            'New edition on side branch of the file sources for testing')

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        self.assertIn('refs/pull/1/head', list(repo.listall_references()))

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference('refs/pull/1/head')
        commit = pr_ref.get_object()
        self.assertEqual(commit.oid.hex, diff_commits[0].oid.hex)
Exemplo n.º 2
0
def get_git_tags_objects(project):
    """ Returns the list of references of the tags created in the git
    repositorie the specified project.
    The list is sorted using the time of the commit associated to the tag """
    repopath = pagure.get_repo_path(project)
    repo_obj = PagureRepo(repopath)
    tags = {}
    for tag in repo_obj.listall_references():
        if 'refs/tags/' in tag and repo_obj.lookup_reference(tag):
            commit_time = ""
            theobject = repo_obj[repo_obj.lookup_reference(tag).target]
            objecttype = ""
            if isinstance(theobject, pygit2.Tag):
                commit_time = theobject.get_object().commit_time
                objecttype = "tag"
            elif isinstance(theobject, pygit2.Commit):
                commit_time = theobject.commit_time
                objecttype = "commit"

            tags[commit_time] = {
                "object": repo_obj[repo_obj.lookup_reference(tag).target],
                "tagname": tag.replace("refs/tags/", ""),
                "date": commit_time,
                "objecttype": objecttype
            }
    sorted_tags = []

    for tag in sorted(tags, reverse=True):
        sorted_tags.append(tags[tag])

    return sorted_tags
Exemplo n.º 3
0
def get_git_tags_objects(project):
    """ Returns the list of references of the tags created in the git
    repositorie the specified project.
    """
    repopath = pagure.get_repo_path(project)
    repo_obj = PagureRepo(repopath)
    tags = [
        repo_obj.lookup_reference(tag)
        for tag in repo_obj.listall_references() if 'refs/tags/' in tag
    ]
    return tags
Exemplo n.º 4
0
def get_git_tags(project):
    """ Returns the list of tags created in the git repositorie of the
    specified project.
    """
    repopath = pagure.get_repo_path(project)
    repo_obj = PagureRepo(repopath)
    tags = [
        tag.split('refs/tags/')[1] for tag in repo_obj.listall_references()
        if 'refs/tags/' in tag
    ]
    return tags
Exemplo n.º 5
0
    def test_get_pr_info_raises(self):
        """ Test pagure.ui.fork._get_pr_info """

        gitrepo = os.path.join(self.path, 'repos', 'test.git')
        gitrepo2 = os.path.join(self.path, 'repos', 'forks', 'pingou',
                                'test.git')

        self.assertRaises(pagure.exceptions.BranchNotFoundException,
                          pagure.lib.git.get_diff_info,
                          repo_obj=PagureRepo(gitrepo2),
                          orig_repo=PagureRepo(gitrepo),
                          branch_from='feature',
                          branch_to='master')

        self.assertRaises(pagure.exceptions.BranchNotFoundException,
                          pagure.lib.git.get_diff_info,
                          repo_obj=PagureRepo(gitrepo2),
                          orig_repo=PagureRepo(gitrepo),
                          branch_from='feature_foo',
                          branch_to='bar')
Exemplo n.º 6
0
    def test_get_pr_info(self):
        """ Test pagure.ui.fork._get_pr_info """

        gitrepo = os.path.join(self.path, 'repos', 'test.git')
        gitrepo2 = os.path.join(self.path, 'repos', 'forks', 'pingou',
                                'test.git')

        diff, diff_commits, orig_commit = pagure.lib.git.get_diff_info(
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            branch_from='feature_foo',
            branch_to='master')
        self.assertEqual(len(diff_commits), 2)
        self.assertEqual(
            diff_commits[0].message,
            'Second edit on side branch of the file sources for testing')
        self.assertEqual(
            diff_commits[1].message,
            'New edition on side branch of the file sources for testing')
        self.assertEqual(orig_commit.message,
                         'Editing the file sources for testing #5')
Exemplo n.º 7
0
    def test_two_diff_pull_request_sequentially(self):
        """ Test calling pagure.lib.git.diff_pull_request twice returns
        the same data
        """
        gitrepo = os.path.join(self.path, 'repos', 'test.git')
        gitrepo2 = os.path.join(self.path, 'repos', 'forks', 'pingou',
                                'test.git')
        request = pagure.lib.query.search_pull_requests(self.session,
                                                        requestid=1,
                                                        project_id=1)

        # Get the diff corresponding to the PR and check its ref

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            with_diff=True)

        self.assertEqual(len(diff_commits), 2)

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        self.assertIn('refs/pull/1/head', list(repo.listall_references()))

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference('refs/pull/1/head')
        commit = pr_ref.get_object()
        self.assertEqual(commit.oid.hex, diff_commits[0].oid.hex)

        # Run diff_pull_request a second time

        diff_commits2, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            with_diff=True)
        self.assertEqual(len(diff_commits2), 2)
        self.assertEqual([d.oid.hex for d in diff_commits2],
                         [d.oid.hex for d in diff_commits])

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        self.assertIn('refs/pull/1/head', list(repo.listall_references()))

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference('refs/pull/1/head')
        commit2 = pr_ref.get_object()
        self.assertEqual(commit2.oid.hex, diff_commits[0].oid.hex)

        self.assertEqual(commit.oid.hex, commit2.oid.hex)
Exemplo n.º 8
0
    def test_get_pr_info_raises(self):
        """ Test pagure.ui.fork._get_pr_info """

        gitrepo = os.path.join(self.path, "repos", "test.git")
        gitrepo2 = os.path.join(self.path, "repos", "forks", "pingou",
                                "test.git")

        self.assertRaises(
            pagure.exceptions.BranchNotFoundException,
            pagure.lib.git.get_diff_info,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            branch_from="feature",
            branch_to="master",
        )

        self.assertRaises(
            pagure.exceptions.BranchNotFoundException,
            pagure.lib.git.get_diff_info,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            branch_from="feature_foo",
            branch_to="bar",
        )
Exemplo n.º 9
0
    def test_get_pr_info(self):
        """ Test pagure.ui.fork._get_pr_info """

        gitrepo = os.path.join(self.path, "repos", "test.git")
        gitrepo2 = os.path.join(self.path, "repos", "forks", "pingou",
                                "test.git")

        diff, diff_commits, orig_commit = pagure.lib.git.get_diff_info(
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            branch_from="feature_foo",
            branch_to="master",
        )
        self.assertEqual(len(diff_commits), 2)
        self.assertEqual(
            diff_commits[0].message,
            "Second edit on side branch of the file sources for testing",
        )
        self.assertEqual(
            diff_commits[1].message,
            "New edition on side branch of the file sources for testing",
        )
        self.assertEqual(orig_commit.message,
                         "Editing the file sources for testing #5")
Exemplo n.º 10
0
def get_git_tags_objects(project):
    """ Returns the list of references of the tags created in the git
    repositorie the specified project.
    The list is sorted using the time of the commit associated to the tag """
    repopath = pagure.get_repo_path(project)
    repo_obj = PagureRepo(repopath)
    tags = {}
    for tag in repo_obj.listall_references():
        if 'refs/tags/' in tag and repo_obj.lookup_reference(tag):
            commit_time = ""
            theobject = repo_obj[repo_obj.lookup_reference(tag).target]
            objecttype = ""
            if isinstance(theobject, pygit2.Tag):
                commit_time = theobject.get_object().commit_time
                objecttype = "tag"
            elif isinstance(theobject, pygit2.Commit):
                commit_time = theobject.commit_time
                objecttype = "commit"

            tags[commit_time] = {
                "object": repo_obj[repo_obj.lookup_reference(tag).target],
                "tagname": tag.replace("refs/tags/", ""),
                "date": commit_time,
                "objecttype": objecttype,
                "head_msg": None,
                "body_msg": None,
            }
            if objecttype == 'tag':
                head_msg, _, body_msg = tags[commit_time][
                    "object"].message.partition('\n')
                if body_msg.strip().endswith('\n-----END PGP SIGNATURE-----'):
                    body_msg = body_msg.rsplit('-----BEGIN PGP SIGNATURE-----',
                                               1)[0].strip()
                tags[commit_time]["head_msg"] = head_msg
                tags[commit_time]["body_msg"] = body_msg
    sorted_tags = []

    for tag in sorted(tags, reverse=True):
        sorted_tags.append(tags[tag])

    return sorted_tags
Exemplo n.º 11
0
def merge_pull_request(session,
                       request,
                       username,
                       request_folder,
                       domerge=True):
    ''' Merge the specified pull-request.
    '''
    if request.remote:
        # Get the fork
        repopath = pagure.get_remote_repo_path(request.remote_git,
                                               request.branch_from)
    else:
        # Get the fork
        repopath = pagure.get_repo_path(request.project_from)

    fork_obj = PagureRepo(repopath)

    # Get the original repo
    parentpath = pagure.get_repo_path(request.project)

    # Clone the original repo into a temp folder
    newpath = tempfile.mkdtemp(prefix='pagure-pr-merge')
    new_repo = pygit2.clone_repository(parentpath, newpath)

    # Update the start and stop commits in the DB, one last time
    diff_commits = diff_pull_request(session,
                                     request,
                                     PagureRepo(parentpath),
                                     fork_obj,
                                     requestfolder=request_folder,
                                     with_diff=False)[0]

    if request.project.settings.get(
            'Enforce_signed-off_commits_in_pull-request', False):
        for commit in diff_commits:
            if 'signed-off-by' not in commit.message.lower():
                raise pagure.exceptions.PagureException(
                    'This repo enforces that all commits are '
                    'signed off by their author. ')

    # Checkout the correct branch
    branch_ref = get_branch_ref(new_repo, request.branch)
    if not branch_ref:
        shutil.rmtree(newpath)
        raise pagure.exceptions.BranchNotFoundException(
            'Branch %s could not be found in the repo %s' %
            (request.branch, request.project.fullname))

    new_repo.checkout(branch_ref)

    branch = get_branch_ref(fork_obj, request.branch_from)
    if not branch:
        shutil.rmtree(newpath)
        raise pagure.exceptions.BranchNotFoundException(
            'Branch %s could not be found in the repo %s' %
            (request.branch_from, request.project_from.fullname
             if request.project_from else request.remote_git))

    repo_commit = fork_obj[branch.get_object().hex]

    ori_remote = new_repo.remotes[0]
    # Add the fork as remote repo
    reponame = '%s_%s' % (request.user.user, request.uid)

    remote = new_repo.create_remote(reponame, repopath)

    # Fetch the commits
    remote.fetch()

    merge = new_repo.merge(repo_commit.oid)
    if merge is None:
        mergecode = new_repo.merge_analysis(repo_commit.oid)[0]

    refname = '%s:refs/heads/%s' % (branch_ref.name, request.branch)
    if ((merge is not None and merge.is_uptodate) or
        (merge is None and mergecode & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE)):

        if domerge:
            pagure.lib.close_pull_request(session,
                                          request,
                                          username,
                                          requestfolder=request_folder)
            try:
                session.commit()
            except SQLAlchemyError as err:  # pragma: no cover
                session.rollback()
                pagure.APP.logger.exception(err)
                shutil.rmtree(newpath)
                raise pagure.exceptions.PagureException(
                    'Could not close this pull-request')
            raise pagure.exceptions.PagureException(
                'Nothing to do, changes were already merged')
        else:
            request.merge_status = 'NO_CHANGE'
            session.commit()
            return 'NO_CHANGE'

    elif (
        (merge is not None and merge.is_fastforward) or
        (merge is None and mergecode & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD)):

        if domerge:
            if merge is not None:
                # This is depending on the pygit2 version
                branch_ref.target = merge.fastforward_oid
            elif merge is None and mergecode is not None:
                branch_ref.set_target(repo_commit.oid.hex)

            PagureRepo.push(ori_remote, refname)
        else:
            request.merge_status = 'FFORWARD'
            session.commit()
            return 'FFORWARD'

    else:
        tree = None
        try:
            tree = new_repo.index.write_tree()
        except pygit2.GitError:
            shutil.rmtree(newpath)
            if domerge:
                raise pagure.exceptions.PagureException('Merge conflicts!')
            else:
                request.merge_status = 'CONFLICTS'
                session.commit()
                return 'CONFLICTS'

        if not domerge:
            request.merge_status = 'MERGE'
            session.commit()
            return 'MERGE'

        head = new_repo.lookup_reference('HEAD').get_object()
        new_repo.create_commit('refs/heads/%s' % request.branch,
                               repo_commit.author, repo_commit.committer,
                               'Merge #%s `%s`' % (request.id, request.title),
                               tree, [head.hex, repo_commit.oid.hex])
        PagureRepo.push(ori_remote, refname)

    # Update status
    pagure.lib.close_pull_request(
        session,
        request,
        username,
        requestfolder=request_folder,
    )
    try:
        # Reset the merge_status of all opened PR to refresh their cache
        pagure.lib.reset_status_pull_request(session, request.project)
        session.commit()
    except SQLAlchemyError as err:  # pragma: no cover
        session.rollback()
        pagure.APP.logger.exception(err)
        shutil.rmtree(newpath)
        raise pagure.exceptions.PagureException(
            'Could not update this pull-request in the database')
    shutil.rmtree(newpath)

    return 'Changes merged!'
Exemplo n.º 12
0
    def test_diff_pull_request_updated(self):
        """ Test that calling pagure.lib.git.diff_pull_request on an updated
        PR updates the PR reference
        """
        gitrepo = os.path.join(self.path, 'repos', 'test.git')
        gitrepo2 = os.path.join(self.path, 'repos', 'forks', 'pingou',
                                'test.git')
        request = pagure.lib.search_pull_requests(self.session,
                                                  requestid=1,
                                                  project_id=1)

        # Get the diff corresponding to the PR and check its ref

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            requestfolder=None,
            with_diff=True)

        self.assertEqual(len(diff_commits), 2)

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        while 1:
            if 'refs/pull/1/head' in list(repo.listall_references()):
                break
            cnt += 1
            if cnt == 60:
                break
            time.sleep(0.5)

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference('refs/pull/1/head')
        commit = pr_ref.get_object()
        self.assertEqual(commit.oid.hex, diff_commits[0].oid.hex)

        # Add a new commit on the fork
        repopath = os.path.join(self.path, 'pingou_test2')
        clone_repo = pygit2.clone_repository(gitrepo2,
                                             repopath,
                                             checkout_branch='feature_foo')

        with open(os.path.join(repopath, 'sources'), 'w') as stream:
            stream.write('foo\n bar\nbaz\nhey there\n')
        clone_repo.index.add('sources')
        clone_repo.index.write()

        last_commit = clone_repo.lookup_branch('feature_foo').get_object()

        # Commits the files added
        tree = clone_repo.index.write_tree()
        author = pygit2.Signature('Alice Author', '*****@*****.**')
        committer = pygit2.Signature('Cecil Committer', '*****@*****.**')
        last_commit = clone_repo.create_commit(
            'refs/heads/feature_foo',  # the name of the reference to update
            author,
            committer,
            'Third edit on side branch of the file sources for testing',
            # binary string representing the tree object ID
            tree,
            # list of binary strings representing parents of the new commit
            [last_commit.oid.hex])

        # Push to the fork repo
        ori_remote = clone_repo.remotes[0]
        refname = 'refs/heads/feature_foo:refs/heads/feature_foo'
        PagureRepo.push(ori_remote, refname)

        # Get the new diff for that PR and check its new ref

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            requestfolder=None,
            with_diff=True)
        self.assertEqual(len(diff_commits), 3)

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        while 1:
            if 'refs/pull/1/head' in list(repo.listall_references()):
                break
            cnt += 1
            if cnt == 60:
                break
            time.sleep(0.5)

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference('refs/pull/1/head')
        commit2 = pr_ref.get_object()
        self.assertEqual(commit2.oid.hex, diff_commits[0].oid.hex)
        self.assertNotEqual(
            commit.oid.hex,
            commit2.oid.hex,
        )
Exemplo n.º 13
0
    def test_diff_pull_request_updated(self):
        """ Test that calling pagure.lib.git.diff_pull_request on an updated
        PR updates the PR reference
        """
        gitrepo = os.path.join(self.path, "repos", "test.git")
        gitrepo2 = os.path.join(self.path, "repos", "forks", "pingou",
                                "test.git")
        request = pagure.lib.query.search_pull_requests(self.session,
                                                        requestid=1,
                                                        project_id=1)

        # Get the diff corresponding to the PR and check its ref

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            with_diff=True,
        )

        self.assertEqual(len(diff_commits), 2)

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        self.assertIn("refs/pull/1/head", list(repo.listall_references()))

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference("refs/pull/1/head")
        commit = pr_ref.peel()
        self.assertEqual(commit.oid.hex, diff_commits[0].oid.hex)

        # Add a new commit on the fork
        repopath = os.path.join(self.path, "pingou_test2")
        clone_repo = pygit2.clone_repository(gitrepo2,
                                             repopath,
                                             checkout_branch="feature_foo")

        with open(os.path.join(repopath, "sources"), "w") as stream:
            stream.write("foo\n bar\nbaz\nhey there\n")
        clone_repo.index.add("sources")
        clone_repo.index.write()

        last_commit = clone_repo.lookup_branch("feature_foo").peel()

        # Commits the files added
        tree = clone_repo.index.write_tree()
        author = pygit2.Signature("Alice Author", "*****@*****.**")
        committer = pygit2.Signature("Cecil Committer", "*****@*****.**")
        last_commit = clone_repo.create_commit(
            "refs/heads/feature_foo",  # the name of the reference to update
            author,
            committer,
            "Third edit on side branch of the file sources for testing",
            # binary string representing the tree object ID
            tree,
            # list of binary strings representing parents of the new commit
            [last_commit.oid.hex],
        )

        # Push to the fork repo
        ori_remote = clone_repo.remotes[0]
        refname = "refs/heads/feature_foo:refs/heads/feature_foo"
        PagureRepo.push(ori_remote, refname)

        # Get the new diff for that PR and check its new ref

        diff_commits, diff = pagure.lib.git.diff_pull_request(
            self.session,
            request=request,
            repo_obj=PagureRepo(gitrepo2),
            orig_repo=PagureRepo(gitrepo),
            with_diff=True,
        )
        self.assertEqual(len(diff_commits), 3)

        # Check that the PR has its PR refs
        # we don't know the task id but we'll give it 30 sec to finish
        cnt = 0
        repo = PagureRepo(gitrepo)
        self.assertIn("refs/pull/1/head", list(repo.listall_references()))

        self.assertTrue(cnt < 60)

        pr_ref = repo.lookup_reference("refs/pull/1/head")
        commit2 = pr_ref.peel()
        self.assertEqual(commit2.oid.hex, diff_commits[0].oid.hex)
        self.assertNotEqual(commit.oid.hex, commit2.oid.hex)