def prune_branch_local(self, branch, force): """Prune branch in repository""" branch_output = fmt.ref_string(branch) if branch not in self.repo.heads: self._print(' - Local branch ' + branch_output + " doesn't exist") return prune_branch = self.repo.heads[branch] if self.repo.head.ref == prune_branch: ref_output = fmt.ref_string(self.truncate_ref(self.default_ref)) try: self._print(' - Checkout ref ' + ref_output) self.repo.git.checkout(self.truncate_ref(self.default_ref)) except GitError as err: message = colored(' - Failed to checkout ref', 'red') + ref_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit() try: self._print(' - Delete local branch ' + branch_output) self.repo.delete_head(branch, force=force) return except GitError as err: message = colored(' - Failed to delete local branch ', 'red') + branch_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _reset_head(self, branch=None): """Reset head of repo, discarding changes :param Optional[str] branch: Branch to reset head to """ if branch is None: try: self.repo.head.reset(index=True, working_tree=True) except GitError as err: ref_output = fmt.ref_string('HEAD') message = colored(' - Failed to reset ', 'red') + ref_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit() else: return 0 try: self.repo.git.reset('--hard', branch) except GitError as err: branch_output = fmt.ref_string(branch) message = colored(' - Failed to reset to ', 'red') + branch_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit() else: return 0
def _create_branch_remote_tracking(self, branch, remote, depth): """Create remote tracking branch :param str branch: Branch name :param str remote: Remote name :param int depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer """ branch_output = fmt.ref_string(branch) self.fetch(remote, depth=depth, ref=branch) if branch in self._remote(remote).refs: self._print_existing_remote_branch_message(branch) return try: self._print(' - Push remote branch ' + branch_output) self.repo.git.push(remote, branch) self._set_tracking_branch(remote, branch) except GitError as err: message = colored(' - Failed to push remote branch ', 'red') + branch_output self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def _clean(self, args): """Clean git directory""" try: self.repo.git.clean(args) except GitError as err: message = colored(' - Failed to clean git repo', 'red') self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def get_current_timestamp(self): """Get current timestamp of HEAD commit""" try: return self.repo.git.log('-1', '--format=%cI') except GitError as err: message = colored(' - Failed to find rev from timestamp', 'red') self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def _find_rev_by_timestamp(self, timestamp, ref): """Find rev by timestamp""" try: return self.repo.git.log('-1', '--format=%H', '--before=' + timestamp, ref) except GitError as err: message = colored(' - Failed to find rev from timestamp', 'red') self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def _abort_rebase(self): """Abort rebase""" if not self._is_rebase_in_progress(): return try: self.repo.git.rebase('--abort') except GitError as err: self._print(colored(' - Failed to abort rebase', 'red')) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def _checkout_tag(self, tag): """Checkout commit tag is pointing to""" tag_output = fmt.ref_string(tag) if tag not in self.repo.tags: self._print(' - No existing tag ' + tag_output) return 1 try: same_commit = self.repo.head.commit == self.repo.tags[tag].commit is_detached = self.repo.head.is_detached if same_commit and is_detached: self._print(' - On correct commit for tag') return 0 self._print(' - Checkout tag ' + tag_output) self.repo.git.checkout('refs/tags/' + tag) return 0 except (GitError, ValueError) as err: message = colored(' - Failed to checkout tag ', 'red') self._print(message + tag_output) self._print(fmt.error(err)) self._exit( fmt.parallel_exception_error(self.repo_path, message, tag_output)) except (KeyboardInterrupt, SystemExit): self._exit()
def _set_tracking_branch(self, remote, branch, remove_dir=False): """Set tracking branch .. py:function:: _set_tracking_branch(remote, branch, remove_dir=False) :param str remote: Remote name :param str branch: Branch name :param Optional[bool] remove_dir: Whether to remove the directory if commands fail """ branch_output = fmt.ref_string(branch) remote_output = fmt.remote_string(remote) origin = self._remote(remote) try: local_branch = self.repo.heads[branch] remote_branch = origin.refs[branch] self._print(' - Set tracking branch ' + branch_output + ' -> ' + remote_output + ' ' + branch_output) local_branch.set_tracking_branch(remote_branch) except GitError as err: message = colored(' - Failed to set tracking branch ', 'red') + branch_output if remove_dir: remove_directory(self.repo_path) self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()
def _checkout_branch_local(self, branch, remove_dir=False): """Checkout local branch .. py:function:: _checkout_branch_local(branch, remove_dir=False) :param str branch: Branch name :param Optional[bool] remove_dir: Whether to remove the directory if commands fail """ branch_output = fmt.ref_string(branch) try: self._print(' - Checkout branch ' + branch_output) default_branch = self.repo.heads[branch] default_branch.checkout() except GitError as err: if remove_dir: remove_directory(self.repo_path) message = colored(' - Failed to checkout branch ', 'red') self._print(message + branch_output) self._print(fmt.error(err)) self._exit( fmt.parallel_exception_error(self.repo_path, message, branch_output)) except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()
def _init_repo(self): """Initialize repository :raise OSError: """ if existing_git_repository(self.repo_path): return try: self._print(' - Initialize repo at ' + fmt.get_path(self.repo_path)) if not os.path.isdir(self.repo_path): try: os.makedirs(self.repo_path) except OSError as err: if err.errno != os.errno.EEXIST: raise self.repo = Repo.init(self.repo_path) except GitError as err: remove_directory(self.repo_path) message = colored(' - Failed to initialize repository', 'red') self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): remove_directory(self.repo_path) self._exit()
def _create_remote(self, remote, url, remove_dir=False): """Create new remote .. py:function:: _create_remote(remote, url, remove_dir=False) :param str remote: Remote name :param str url: URL of repo :param Optional[bool] remove_dir: Whether to remove the directory if commands fail """ remote_names = [r.name for r in self.repo.remotes] if remote in remote_names: return 0 remote_output = fmt.remote_string(remote) try: self._print(' - Create remote ' + remote_output) self.repo.create_remote(remote, url) return 0 except GitError as err: message = colored(' - Failed to create remote ', 'red') if remove_dir: remove_directory(self.repo_path) self._print(message + remote_output) self._print(fmt.error(err)) self._exit( fmt.parallel_exception_error(self.repo_path, message, remote_output)) except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()
def _create_remote(self, remote, url, remove_dir=False): """Create new remote""" remote_names = [r.name for r in self.repo.remotes] if remote in remote_names: return 0 remote_output = fmt.remote_string(remote) try: self._print(' - Create remote ' + remote_output) self.repo.create_remote(remote, url) return 0 except GitError as err: message = colored(' - Failed to create remote ', 'red') if remove_dir: remove_directory(self.repo_path) self._print(message + remote_output) self._print(fmt.error(err)) self._exit( fmt.parallel_exception_error(self.repo_path, message, remote_output)) except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()
def _checkout_new_repo_commit(self, commit, remote, depth): """Checkout commit or fail and delete repo if it doesn't exist :param str commit: Commit sha :param str remote: Remote name :param int depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer """ commit_output = fmt.ref_string(commit) self._remote(remote, remove_dir=True) self.fetch(remote, depth=depth, ref=commit, remove_dir=True) self._print(' - Checkout commit ' + commit_output) try: self.repo.git.checkout(commit) except GitError as err: remove_directory(self.repo_path) message = colored(' - Failed to checkout commit ', 'red') self._print(message + commit_output) self._print(fmt.error(err)) self._exit( fmt.parallel_exception_error(self.repo_path, message, commit_output)) except (KeyboardInterrupt, SystemExit): remove_directory(self.repo_path) self._exit()
def _validate_clowder_yaml(self): """Print invalid yaml message and exit if invalid""" if self._invalid_yaml: print(fmt.invalid_yaml_error()) print(fmt.error(self._error)) sys.exit(1)
def checkout(self, truncated_ref, allow_failure=False): """Checkout git ref .. py:function:: checkout(truncated_ref, allow_failure=False) :param str truncated_ref: Ref to git checkout :param Optional[bool] allow_failure: Whether to allow failing to checkout branch """ ref_output = fmt.ref_string(truncated_ref) try: self._print(' - Check out ' + ref_output) if self._print_output: print(self.repo.git.checkout(truncated_ref)) return self.repo.git.checkout(truncated_ref) except GitError as err: message = colored(' - Failed to checkout ', 'red') self._print(message + ref_output) if allow_failure: return self._print(fmt.error(err)) self._exit(fmt.parallel_exception_error(self.repo_path, message, ref_output)) except (KeyboardInterrupt, SystemExit): self._exit()
def _set_tracking_branch(self, remote, branch, remove_dir=False): """Set tracking branch""" branch_output = fmt.ref_string(branch) remote_output = fmt.remote_string(remote) origin = self._remote(remote) try: local_branch = self.repo.heads[branch] remote_branch = origin.refs[branch] self._print(' - Set tracking branch ' + branch_output + ' -> ' + remote_output + ' ' + branch_output) local_branch.set_tracking_branch(remote_branch) return 0 except GitError as err: message = colored(' - Failed to set tracking branch ', 'red') + branch_output if remove_dir: remove_directory(self.repo_path) self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()
def _invalid_yaml_error(error): """Print invalid yaml message and raise exception :param Exception error: Exception raised during yaml validation/loading :raise ClowderExit: """ print(fmt.invalid_yaml_error()) print(fmt.error(error)) raise ClowderExit(42)
def _find_rev_by_timestamp(self, timestamp, ref): """Find rev by timestamp :param str timestamp: Commit ref timestamp :param str ref: Reference ref :return: Commit sha at or before timestamp :rtype: str """ try: return self.repo.git.log('-1', '--format=%H', '--before=' + timestamp, ref) except GitError as err: message = colored(' - Failed to find rev from timestamp', 'red') self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def push(self): """Push changes""" try: self._print(' - Push local changes') print(self.repo.git.push()) except GitError as err: message = colored(' - Failed to push local changes', 'red') self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def commit(self, message): """Commit current changes""" try: self._print(' - Commit current changes') print(self.repo.git.commit(message=message)) except GitError as err: message = colored(' - Failed to commit current changes', 'red') self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _create_branch_remote_tracking(self, branch, remote, depth): """Create remote tracking branch""" branch_output = fmt.ref_string(branch) origin = self._remote(remote) return_code = self.fetch(remote, depth=depth, ref=branch) if return_code != 0: self._exit('', return_code=return_code) if branch in origin.refs: try: self.repo.git.config('--get', 'branch.' + branch + '.merge') self._print(' - Tracking branch ' + branch_output + ' already exists') return except GitError: message_1 = colored(' - Remote branch ', 'red') message_2 = colored(' already exists', 'red') message = message_1 + branch_output + message_2 + '\n' self._print(message) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit() try: self._print(' - Push remote branch ' + branch_output) self.repo.git.push(remote, branch) return_code = self._set_tracking_branch(remote, branch) if return_code != 0: self._exit('', return_code=return_code) except GitError as err: message = colored(' - Failed to push remote branch ', 'red') + branch_output self._print(message) self._print(fmt.error(err)) self._exit(fmt.error(err)) except (KeyboardInterrupt, SystemExit): self._exit()
def _submodule_command(self, *args, **kwargs): """Base submodule command""" try: self.repo.git.submodule(*args) except (GitError, ValueError) as err: message = colored( str(kwargs.get('error_msg', ' - Submodule command failed')), 'red') self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def add(self, files): """Add files to git index""" self._print(' - Add files to git index') try: print(self.repo.git.add(files)) except GitError as err: message = cprint(' - Failed to add files to git index\n', 'red') + fmt.error(err) self._print(message) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit() else: self.status_verbose()
def _repo(self): """Create Repo instance for path""" try: repo = Repo(self.repo_path) return repo except GitError as err: repo_path_output = fmt.path(self.repo_path) message = colored(" - Failed to create Repo instance for ", 'red') + repo_path_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _remote(self, remote, remove_dir=False): """Get remote""" remote_output = fmt.remote_string(remote) try: return self.repo.remotes[remote] except GitError as err: message = colored(' - No existing remote ', 'red') + remote_output if remove_dir: remove_directory(self.repo_path) self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _is_tracking_branch(self, branch): """Check if branch is a tracking branch""" branch_output = fmt.ref_string(branch) try: local_branch = self.repo.heads[branch] tracking_branch = local_branch.tracking_branch() return True if tracking_branch else False except GitError as err: message = colored(' - No existing branch ', 'red') + branch_output self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _create_branch_local(self, branch): """Create local branch""" branch_output = fmt.ref_string(branch) try: self._print(' - Create branch ' + branch_output) self.repo.create_head(branch) return 0 except GitError as err: message = colored(' - Failed to create branch ', 'red') self._print(message + branch_output) self._print(fmt.error(err)) return 1 except (KeyboardInterrupt, SystemExit): self._exit()
def _untracked_files(self): """Execute command and display continuous output""" command = "git ls-files -o -d --exclude-standard | sed q | wc -l| tr -d '[:space:]'" try: output = subprocess.check_output(command, shell=True, cwd=self.repo_path) return output.decode('utf-8') == '1' except GitError as err: message = colored(' - Failed to check untracked files', 'red') self._print(message) self._print(fmt.error(err)) self._exit(message) except (KeyboardInterrupt, SystemExit): self._exit()
def _checkout_new_repo_tag(self, tag, remote, depth, remove_dir=False): """Checkout tag or fail and delete repo if it doesn't exist""" tag_output = fmt.ref_string(tag) self._remote(remote, remove_dir=remove_dir) self.fetch(remote, depth=depth, ref='refs/tags/' + tag, remove_dir=remove_dir) try: remote_tag = self.repo.tags[tag] except (GitError, IndexError): message = ' - No existing tag ' if remove_dir: remove_directory(self.repo_path) self._print(colored(message, 'red') + tag_output) self._exit( fmt.parallel_exception_error(self.repo_path, colored(message, 'red'), tag_output)) if self.print_output: self._print(message + tag_output) return 1 except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit() else: try: self._print(' - Checkout tag ' + tag_output) self.repo.git.checkout(remote_tag) return 0 except GitError as err: message = colored(' - Failed to checkout tag ', 'red') self._print(message + tag_output) self._print(fmt.error(err)) if remove_dir: remove_directory(self.repo_path) self._exit( fmt.parallel_exception_error(self.repo_path, message, tag_output)) return 1 except (KeyboardInterrupt, SystemExit): if remove_dir: remove_directory(self.repo_path) self._exit()