Ejemplo n.º 1
0
    def test_merge_request(self, mergerequest_iid=None):
        """
        Test a mergerequest localy

        Fetch the content of a mergerequest and put it into a local
        branch so that one can test and inspect the changes before
        accepting the MR.
        """

        __ret = []

        if not git.is_git_repo():
            __ret.append(('WARNING', "Not a git repository", 1))
            return __ret

        # TODO:
        # Maybe we can create a workflow to git stash automatically.
        # But it feels bad because we just do things with code the owner
        # of this code is not expecting (like stashing)
        if not git.branch_is_clean():
            __ret.append((
                'FAIL',
                "Your current branch is not clean. "
                "Please git stash first your changes.", 1))

            return __ret

        mergerequest_id = self.api.mergerequest_iid_to_id(mergerequest_iid)

        if not self.api.is_mergerequest_open(mergerequest_id):
            __ret.append((
                'FAIL',
                "Mergerequest '{0}' already closed? "
                "Is there a mergerequest with this ID?"
                .format(mergerequest_id), 1))

            return __ret

        values = self.api.get_mergerequest_details(mergerequest_id)
        if not values:
            __ret.append(('FAIL', "Mergerequest not found", 1))
            return __ret

        mr_branch = values['changes']['source_branch']

        if git.branch_exist('test_' + mr_branch):
            __ret.append((
                'FAIL',
                "Branch test_{0} exists!".format(mr_branch), 1))

            return __ret

        __ret.append(('GREEN', "Fetch from origin"))
        git.git(['fetch'])
        __ret.append(('GREEN', "Checkout test_{0}".format(mr_branch)))
        git.git(['checkout', '-b', 'test_' + mr_branch, 'origin/' + mr_branch])
        __ret.append(('GREEN',
                      "Current branch: {0}".
                      format(git.get_current_branch())))
        return __ret
Ejemplo n.º 2
0
    def push_patch(self, assignee_id=None, mr_text=None):
        """
        Push the patch and provide a mergerequest

        The main problem is to avoid CONFLICTs while accepting a MR in
        accept_mergerequest().
        To support that we check if origin/master can be merged to our
        issue branch. If not the committer has to solve the conflict first
        before the patch might be submitted.

        Btw we force the committer not to use the master branch of the
        repository because we want to keep it clean as far as possible.

        After the patch is pushed to the remote as a new branch the MR
        will be created.
        """

        __ret = []

        if git.get_current_branch() == "master":
            __ret.append((
                'WARNING',
                "You can not open a mergerequest from your "
                "local master branch.\n"
                "Please switch to your issue branch!", 1))
            return __ret

        if not git.branch_is_clean():
            output = git.git(['status', '-s'])
            __ret.append(('INFO', output))
            __ret.append(('WARNING', "You have uncommitted changes. Please commit them first!", 1))
            return __ret

        # We have to do some validating:
        # 1. Check whether the current commit is already in
        #    the remote master branch
        # 2. If not if we need to push our local changes to the
        #    remote. There might be 3 reasons:
        #   - The source_branch of the mergerequest doesn't exists
        #     on the remote.
        #   - If there is no source_branch, we have to merge
        #     the origin/master into our issue branch to avoid
        #     conflicts on the origin side.
        #   - The source_branch exists but we have new commits for that MR
        #
        #  We now have our local changes at the remote in a seperate branch.
        #  Move on:
        #
        #  3. If there is no MR present, create one.
        #
        #  Pray.

        # Step 1: Check whether the commit exist in the remote master branch
        last_local_sha = git.get_last_commit_sha()
        sha_is_on_remote = git.is_commit_on_remote(last_local_sha)

        if sha_is_on_remote:
            __ret.append((
                'WARNING',
                "Your local commit is already in the remote master "
                "branch.\nAborting!", 1))
            return __ret

        # Step 2: Check whether we have to push our local changes to the remote

        need_push = False

        sourcebranch = git.get_current_branch()

        __ret.append(('GREEN', 'Branch: {0}'.format(sourcebranch)))

        # First check whether the MR branch exists on the remote
        sourcebranch_on_remote = self.api.remote_branch_exists(sourcebranch)

        if not sourcebranch_on_remote:
            need_push = True
            # We need to merge the origin/master into our issue branch because
            # of avoiding conflicts in the merge workflow on the origin side.
            try:
                __ret.append((
                    'INFO',
                    'Try to rebase origin master into {0}'
                    .format(sourcebranch)))

                git.git(['fetch'])
                git.git(['rebase', 'origin/master'])
            except ValueError as e:
                __ret.append((
                    'FAIL',
                    "Merge into {0} failed: {1}".
                    format(sourcebranch, e.message)))

                git.git(['rebase', '--abort'])
                __ret.append(('INFO', 'Please run \n\ngit pull --rebase\n\nand manually resolve your CONFLICTs.'))
                __ret.append(('INFO', 'Then run\n\ngit add <FILE>\n git rebase --continue'))
                __ret.append(('INFO', 'At least run\n\nnacl-flow cp again', 1))
                return __ret

        else:
            # Second check whether we have un-pushed local commits.
            # We check the local source branch compared to the remote
            # source branch.
            unpushed_commits = git.need_pull_push(
                return__returncode=True,
                local_branch=sourcebranch,
                remote_branch=sourcebranch)
            if unpushed_commits == 2:
                need_push = True

        if need_push:
            __ret.append(('INFO', "Pushing to origin " + sourcebranch))
            git.git(['push', 'origin', sourcebranch])
        else:
            __ret.append(('INFO', "Local and remote are up-to-date."))

        # We are done with pushing commits.
        # Step 3. Creating a MR
        if assignee_id:

            if not check_string_to_int(assignee_id):
                __ret.append(('WARNING', "ID must be an integer", 1))
                return __ret

            assignee_id = int(assignee_id)

        targetbranch = 'master'
        if mr_text:
            title = str(mr_text)
        else:
            title = git.git(['log', '--format=%s', '-n', '1'])
        is_new_mergerequest = self.api.is_mergerequest_new(
            sourcebranch, targetbranch)

        if is_new_mergerequest:
            __ret.append(('GREEN', "Create a new mergerequest"))

            if not self.api.createmergerequest(
                    self.p_id,
                    sourcebranch,
                    targetbranch,
                    title,
                    assignee_id=assignee_id):
                __ret.append(('FAIL', "Creating Mergerequest failed!"))
        else:
            __ret.append(('INFO', "Mergerequests exists. Skipping"))

        return __ret
Ejemplo n.º 3
0
 def test_get_current_branch(self, mock):
     self.assertEqual(get_current_branch(), "master")