def run(self, command: str, ignore_errors: bool) -> None: """Run commands or script in project directory :param str command: Commands to run :param bool ignore_errors: Whether to exit if command returns a non-zero exit code """ if not existing_git_repo(self.full_path): CONSOLE.stdout(fmt.red(" - Project missing\n")) return forall_env = { 'CLOWDER_PATH': ENVIRONMENT.clowder_dir, 'PROJECT_PATH': self.full_path, 'PROJECT_NAME': self.name, 'PROJECT_REMOTE': self.remote, 'PROJECT_REF': self.ref.formatted_ref } # TODO: Add tests for presence of these variables in test scripts # if self.branch: # forall_env['UPSTREAM_BRANCH'] = self.branch # if self.tag: # forall_env['UPSTREAM_TAG'] = self.tag # if self.commit: # forall_env['UPSTREAM_COMMIT'] = self.commit if self.upstream: forall_env['UPSTREAM_REMOTE'] = self.upstream.remote forall_env['UPSTREAM_NAME'] = self.upstream.name forall_env['UPSTREAM_REF'] = self.upstream.ref.formatted_ref self._run_forall_command(command, forall_env, ignore_errors)
def wrapper(*args, **kwargs): """Wrapper""" instance = args[0] if not Path(instance.full_path / '.git').is_dir(): CONSOLE.stdout(fmt.red("- Project missing")) return return func(*args, **kwargs)
def color_project_string(project: str) -> str: """Return formatted colored project name :param str project: Relative project path :return: Formatted project name """ if '*' in project: return fmt.red(project) return fmt.green(project)
def print_remote_branches(self) -> None: """Print remote git branches""" for branch in self.repo.git.branch('-r', '-l', f"{self.remote}*").split('\n'): if ' -> ' in branch: components = branch.split(' -> ') local_branch = components[0] remote_branch = components[1] CONSOLE.stdout(f" {fmt.red(local_branch)} -> {remote_branch}") else: CONSOLE.stdout(fmt.red(branch))
def formatted_ref(self) -> str: """Formatted project repo ref""" local_commits_count = self.new_commits_count() upstream_commits_count = self.new_commits_count(upstream=True) no_local_commits = local_commits_count == 0 or local_commits_count == '0' no_upstream_commits = upstream_commits_count == 0 or upstream_commits_count == '0' if no_local_commits and no_upstream_commits: status = '' else: local_commits_output = fmt.yellow(f'+{local_commits_count}') upstream_commits_output = fmt.red(f'-{upstream_commits_count}') status = f'({local_commits_output}/{upstream_commits_output})' if self.is_detached: return fmt.magenta(fmt.escape(f'[HEAD @ {self.sha()}]')) return fmt.magenta(fmt.escape(f'[{self.current_branch}]')) + status
def status(self, padding: Optional[int] = None) -> str: """Return formatted status for project :param Optional[int] padding: Amount of padding to use for printing project on left and current ref on right :return: Formatting project name and status """ if not existing_git_repo(self.full_path): project_output = self.name if padding: project_output = project_output.ljust(padding) project_output = fmt.green(project_output) missing_output = fmt.red('-') return f'{project_output} {missing_output}' project_output = fmt.green(project_output) return project_output project_output = self.repo.format_project_string(self.path) if padding: project_output = project_output.ljust(padding) project_output = self.repo.color_project_string(project_output) return f'{project_output} {self.repo.formatted_ref}'
def forall(projects: Tuple[ResolvedProject, ...], jobs: int, command: str, ignore_errors: bool) -> None: """Runs command or script for projects in parallel :param Tuple[ResolvedProject, ...] projects: Projects to run command for :param int jobs: Number of jobs to use running parallel commands :param str command: Command to run :param bool ignore_errors: Whether to exit if command returns a non-zero exit code """ CONSOLE.stdout(' - Run forall commands in parallel\n') for project in projects: CONSOLE.stdout(project.status()) if not project.full_path.is_dir(): CONSOLE.stdout(fmt.red(" - Project missing")) forall_func = partial(run_parallel, jobs, projects, 'run', command=command, ignore_errors=ignore_errors) trio.run(forall_func)