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
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
def test_get_current_branch(self, mock): self.assertEqual(get_current_branch(), "master")