Example #1
0
    def write_patch_for_issue(self, issue_id=None):
        """
        Start a patch

        This is intended to be the first step in a process of providing
        a patch.
        Every patch should be written in its own branch. Therefore we
        provide a simple cmd to create a meaningfull named branch related to
        its issue. Thats why the issue id must be provided.
        There some consistency checks around starting a new branch.
        """

        __ret = []

        # first we have to do a few consistency checks
        if not check_string_to_int(issue_id):
            __ret.append(('WARNING', "ID must be an integer", 1))
            return __ret

        issue_id = int(issue_id)

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

        if not git.branch_is_clean():
            __ret.append((
                'WARNING',
                "Your branch is not clean. Please commit your changes first."))
            return __ret

        # Transform iid to id
        try:
            issue_uid = self.api.issue_iid_to_uid(issue_id)

            issue = self.api.getprojectissue(self.p_id, issue_uid)
            if not issue:
                __ret.append(('WARNING', "Issue ID not found", 1))
                return __ret

            if issue['project_id'] != self.p_id:
                __ret.append((
                    'WARNING',
                    "The issue ID does not correspond to the current " +
                    "git repository/project", 1))
                return __ret
        except TypeError as e:
            __ret.append(('FAIL', 'Something went wrong: {0}'. format(e.message)))
            return __ret

        # the workflow itself:
        # 1. create a branch
        # 2. switch to that branch.
        git.change_or_create_branch("issue_" + str(issue_id))
        return __ret
Example #2
0
    def edit_issue(self, issue_id=None, do=None):
        """
        Close or reopen an issue

        'do' must be either 'close' or 'reopen'
        """

        __ret = []

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

        issue_id = int(issue_id)
        issue_uid = self.api.issue_iid_to_uid(issue_id)
        if not issue_uid:
            __ret.append(('FAIL',
                        "Issue {0} not found".format(issue_id), 1))
            return __ret

        if do == 'close':
            state_event = 'close'
        elif do == 'reopen':
            state_event = 'reopen'
        else:
            raise ValueError('do must be close or reopen')

        try:
            ret_val = self.api.edit_issue(issue_uid, state_event=state_event)
            if ret_val['state'] == 'closed':
                __ret.append(('GREEN', 'Issue {0} closed'.format(issue_id)))
            elif ret_val['state'] == 'reopened':
                __ret.append(('GREEN', 'Issue {0} reopened'.format(issue_id)))
            else:
                __ret.append((
                    'FAIL',
                    'Issue {0} has state: {1}'
                    .format(issue_id, ret_val['state'])))
        except:
            __ret.append(('FAIL', 'Something went wrong'))

        return __ret
Example #3
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