def create(self): ''' Creates the tag in the repository ''' command = f'git tag {self.tag_name} {self.sha_commit}' call_subprocess(command, verbose=False) self.sha_commit = self.get_sha_commit(force=True) print(f'{INFO_TAG} Tag {self.tag_name} created ' f'in commit {self.sha_commit}')
def is_commit_user_configured(): get_name = 'git config user.name' get_email = 'git config user.email' name, _ = call_subprocess(get_name, False) email, _ = call_subprocess(get_email, False) return bool(name.strip()) and bool(email.strip())
def cherry_pick(commit_sha): ''' Cherry picks into current branch ''' print(f'{INFO_TAG} Cherry picking \'{commit_sha}\'') create_command = (f'git cherry-pick {commit_sha} -m 1') # TODO check this output, status_code = call_subprocess(create_command, verbose=False) if status_code: raise CouldNotCherryPick(commit_sha, output)
def create_branch(branch_name, do_checkout=True): ''' Creates a branch, can select to checkout on it or not ''' print(f'{INFO_TAG} Creating branch \'{branch_name}\'') create_command = (f'git checkout -b {branch_name}' if do_checkout else f'git branch {branch_name}') output, status_code = call_subprocess(create_command, verbose=False) if status_code: raise CouldNotCreateBranch(branch_name, output)
def get_remote_url(remote, verbose=True): ''' Extracts the remote url of the rmeote passed ''' remotes, _ = call_subprocess('git remote -v', verbose) remote = [ remote_line.replace(' ', '\t').split('\t')[1] for remote_line in remotes.split('\n') if 'fetch' in remote_line and remote in remote_line ] return remote[0] if remote else None
def checkout(branch_name, remote, reset=False): ''' Checkots to passed branch, if reset flag is activated, resets to the branch in the remote ''' print(f'{INFO_TAG} Checking out \'{branch_name}\'') get_actual_branch_command = 'git rev-parse --abbrev-ref HEAD | tr -d "\n"' actual_branch, _ = call_subprocess(get_actual_branch_command, verbose=False) if actual_branch != branch_name: print(f'\t- Checking out {branch_name}') call_subprocess(f'git checkout -f {branch_name}', verbose=True) else: print(f'\t- Currently on target branch') if reset: print(f'\t- Reseting local branch \'{branch_name}\' to remote branch ' f'\'{remote}/{branch_name}\'') call_subprocess(f'git reset --hard {remote}/{branch_name}', verbose=False) print()
def get_branch_list(all_branches=False): ''' Returns a list of the branches in the current repository ''' all_parameter = '-a' if all_branches else '' branches, _ = call_subprocess(f'git branch --list {all_parameter}', verbose=False) branches = [ branch.replace('* ', '').strip() for branch in branches.split('\n') if branch ] return branches
def get_merge_commits(source_branch): ''' Returns the merge commits of the current branch ''' filter_string = (f'--first-parent {source_branch}' if source_branch else '') pretty = f'--pretty=format:' + '$.$'.join([pretty.value['code'] for pretty in PrettyFormat]) list_command = f'git log --merges {pretty} --all {filter_string}' output, _ = call_subprocess(list_command, verbose=False) return [MergeCommit(commit_log=merge_commit) for merge_commit in output.splitlines()]
def fetch(remote, remote_url=None, count=0, verbose=True): ''' Fetchs from the remote ''' remote_url = get_remote_url(remote, verbose=verbose) if not remote_url: print(f'{WARNING_LINE} Remote not found, omiting fetch') print(f'{INFO_TAG} Fetching from {remote} ({remote_url}) ...') _, errcode = call_subprocess(f'git fetch {remote}', verbose=verbose) if errcode > 0 and count > 3: raise CouldNotFetchException(remote) if errcode > 0: fetch(remote, remote_url=remote_url, count=count + 1, verbose=verbose)
def getDifferences(sourceFolder, source, target): ''' Extract the differences between two references ''' diffCommand = f'git diff --name-status {target} {source}' output, _ = call_subprocess(diffCommand) regexString = r'([A-Z0-9]+)\t*({}\/.+)'.format(sourceFolder) differences = re.findall(regexString, output) if not differences: raise NoDifferencesException(sourceFolder) return differences
def create_tag_terminal(self, tagName, commitHash): print( f'{INFO_TAG} Flag -gt detected. Tag will be created by Git Terminal' ) print_key_value_list(f'{INFO_TAG} Creating tag with:', [('Remote URL', self.host), ('Tag Name', tagName), ('Ref', commitHash)]) command = f'git tag {tagName} {commitHash}' stdout, code = call_subprocess(command) if code == 128: raise DuplicateRemote(tagName, commitHash, 'Tag') command = f'git push origin {tagName}' stdout, code = call_subprocess(command) if code == 0: print(f'{INFO_TAG} Tag Created') else: print(f"{WARNING_TAG} Tag Created but not pushed to remote.") raise Exception(code)
def merge(source_branch, target_branch): ''' Merge branches ''' print(f'{INFO_TAG} Merging {source_branch} into {target_branch}') command = (f'git merge --no-ff {source_branch} ' f'-m "Merge branch {source_branch} into {target_branch}"') stdout, errcode = call_subprocess(command) if 'Already up to date.' in stdout: raise BranchesUpToDateException(source_branch, target_branch) if errcode != 0: if 'Merge conflict in' in stdout: raise MergeConflictsException(source_branch, target_branch, parse_conflicts(stdout)) raise MergeException()
def create_branch_terminal(self, branchName, commitHash): print( f'{INFO_TAG} Flag -gt detected. branch will be created by Git Terminal' ) print_key_value_list(f'{INFO_TAG} Creating branch with:', [('Remote URL', self.host), ('Branch Name', branchName), ('Source Ref', commitHash)]) command = f'git checkout -b {branchName} {commitHash}' stdout, code = call_subprocess(command) if code == 128: raise DuplicateRemote(branchName, commitHash, 'Branch') command = f'git push origin {branchName}' stdout, code = call_subprocess(command) if code == 0: print(f'{INFO_TAG} Branch Created') else: print(f"{WARNING_TAG} Branch Created but not pushed to remote.") raise Exception(code)
def __filter_merge_requests(merge_requests, target_branch, remote): ''' Erase merge requests already in target branch ''' fetch(remote, verbose=False) checkout(target_branch, remote, reset=False) command = 'git log --pretty=format:\'%H\'' hashes, _ = call_subprocess(command, verbose=False) hashes = hashes.split('\n') merge_requests = [merge_request for merge_request in merge_requests if merge_request.sha not in hashes] print(f'{INFO_TAG} {len(merge_requests)} Merge Requests after filtering') for merge_request in merge_requests: print(f'\t-{merge_request}') return merge_requests
def get_file(filepath, revision): ''' Prints the file from the passed revision ''' output, _ = call_subprocess(f'git show {revision}:"{filepath}"', False) return output.encode('utf-8')
def get_short_sha(long_sha): ''' Returns the short (5 chars version) of the commit ''' command = f'git rev-parse --short {long_sha}' short_sha, _ = call_subprocess(command, verbose=False) return short_sha.strip()
def is_git_repository(): validate_repo = 'git rev-parse --is-inside-work-tree' _, returncode = call_subprocess(validate_repo, False) return returncode == 0
def is_valid_remote(remote): validate_remote = f'git ls-remote --exit-code {remote}' _, returncode = call_subprocess(validate_remote, False) return returncode == 0
def get_last_tag(): ''' Returns the last tag name of the current branch ''' command = 'git describe --abbrev=0 --tags' stdout, _ = call_subprocess(command, verbose=False) return Tag(stdout)
def get_tag_commit(tag_name): ''' Returns the tag commit associated to the tag name ''' command = f'git rev-list -n 1 {tag_name}' stdout, _ = call_subprocess(command) return stdout.strip()