コード例 #1
0
ファイル: project_repo_impl.py プロジェクト: JrGoodle/clowder
    def _create_branch_local_tracking(self,
                                      branch: str,
                                      remote: str,
                                      depth: int,
                                      fetch: bool = True,
                                      remove_dir: bool = False) -> None:
        """Create and checkout 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
        :param bool fetch: Whether to fetch before creating branch
        :param bool remove_dir: Whether to remove the directory if commands fail
        """

        origin = self._remote(remote, remove_dir=remove_dir)
        if fetch:
            self.fetch(remote,
                       depth=depth,
                       ref=GitRef(branch=branch),
                       remove_dir=remove_dir)

        try:
            CONSOLE.stdout(f' - Create branch {fmt.ref(branch)}')
            self.repo.create_head(branch, origin.refs[branch])
        except BaseException:
            LOG.error(f'Failed to create branch {fmt.ref(branch)}')
            if remove_dir:
                remove_directory(self.repo_path, check=False)
            raise
        else:
            self._set_tracking_branch(remote, branch, remove_dir=remove_dir)
            self._checkout_branch_local(branch, remove_dir=remove_dir)
コード例 #2
0
def config_set_projects(args) -> None:
    """Clowder config set projects command entry point"""

    CONSOLE.stdout(' - Set projects config value')
    config = Config()
    config.projects = tuple(args.projects)
    config.save()
コード例 #3
0
def config_set_rebase(_) -> None:
    """Clowder config set rebase command entry point"""

    CONSOLE.stdout(' - Set rebase config value')
    config = Config()
    config.rebase = True
    config.save()
コード例 #4
0
ファイル: resolved_project.py プロジェクト: JrGoodle/clowder
    def stash(self) -> None:
        """Stash changes for project if dirty"""

        if self.is_dirty:
            self.repo.stash()
        else:
            CONSOLE.stdout(" - No changes to stash")
コード例 #5
0
    def status(self) -> None:
        """Print  git status

        Equivalent to: ``git status``
        """

        CONSOLE.stdout(self.repo.git.status())
コード例 #6
0
def config_clear_all(_) -> None:
    """Clowder config clear all command entry point"""

    CONSOLE.stdout(' - Clear all config values')
    config = Config()
    config.clear()
    config.save()
コード例 #7
0
ファイル: project_repo_impl.py プロジェクト: JrGoodle/clowder
    def _checkout_new_repo_tag(self,
                               tag: str,
                               remote: str,
                               depth: int,
                               remove_dir: bool = False) -> None:
        """Checkout tag or fail and delete repo if it doesn't exist

        :param str tag: Tag name
        :param str remote: Remote name
        :param int depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer
        :param bool remove_dir: Whether to remove the directory if commands fail
        """

        remote_tag = self._get_remote_tag(tag,
                                          remote,
                                          depth=depth,
                                          remove_dir=remove_dir)
        if remote_tag is None:
            return

        try:
            CONSOLE.stdout(f' - Checkout tag {fmt.ref(tag)}')
            self.repo.git.checkout(remote_tag)
        except BaseException:
            LOG.error(f'Failed to checkout tag {fmt.ref(tag)}')
            if remove_dir:
                remove_directory(self.repo_path, check=False)
            raise
コード例 #8
0
def config_clear_protocol(_) -> None:
    """Clowder config clear protocol command entry point"""

    CONSOLE.stdout(' - Clear protocol config value')
    config = Config()
    config.protocol = None
    config.save()
コード例 #9
0
def config_clear_jobs(_) -> None:
    """Clowder config clear jobs command entry point"""

    CONSOLE.stdout(' - Clear jobs config value')
    config = Config()
    config.jobs = None
    config.save()
コード例 #10
0
def config_set_jobs(args) -> None:
    """Clowder config set jobs command entry point"""

    CONSOLE.stdout(' - Set jobs config value')
    config = Config()
    config.jobs = args.jobs[0]
    config.save()
コード例 #11
0
def config_clear_rebase(_) -> None:
    """Clowder config clear rebase command entry point"""

    CONSOLE.stdout(' - Clear rebase config value')
    config = Config()
    config.rebase = None
    config.save()
コード例 #12
0
def herd(projects: Tuple[ResolvedProject, ...],
         jobs: int,
         branch: Optional[str] = None,
         tag: Optional[str] = None,
         depth: Optional[int] = None,
         rebase: bool = False) -> None:
    """Clone projects or update latest from upstream in parallel

    :param Tuple[ResolvedProject, ...] projects: Projects to herd
    :param int jobs: Number of jobs to use running parallel commands
    :param Optional[str] branch: Branch to attempt to herd
    :param Optional[str] tag: Tag to attempt to herd
    :param Optional[int] depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer
    :param bool rebase: Whether to use rebase instead of pulling latest changes
    """

    CONSOLE.stdout(' - Herd projects in parallel\n')
    CLOWDER_CONTROLLER.validate_print_output(projects)

    run_func = partial(run_parallel,
                       jobs,
                       projects,
                       'herd',
                       branch=branch,
                       tag=tag,
                       depth=depth,
                       rebase=rebase)
    trio.run(run_func)
コード例 #13
0
ファイル: resolved_project.py プロジェクト: JrGoodle/clowder
    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)
コード例 #14
0
ファイル: forall.py プロジェクト: JrGoodle/clowder
def _forall_impl(command: str,
                 ignore_errors: bool,
                 projects: List[str],
                 jobs: Optional[int] = None) -> None:
    """Runs script in project directories specified

    :param str command: Command or script and optional arguments
    :param bool ignore_errors: Whether to exit if command returns a non-zero exit code
    :param List[str] projects: Project names to clean
    :param Optional[int] jobs: Number of jobs to use running parallel commands
    """

    projects = Config().process_projects_arg(projects)
    projects = CLOWDER_CONTROLLER.filter_projects(CLOWDER_CONTROLLER.projects,
                                                  projects)

    jobs_config = Config().jobs
    jobs = jobs_config if jobs_config is not None else jobs

    if jobs is not None and jobs != 1 and os.name == "posix":
        if jobs <= 0:
            jobs = 4
        parallel.forall(projects, jobs, command, ignore_errors)
        return

    for project in projects:
        CONSOLE.stdout(project.status())
        project.run(command, ignore_errors=ignore_errors)
コード例 #15
0
ファイル: project_repo.py プロジェクト: JrGoodle/clowder
    def start(self, remote: str, branch: str, depth: int, tracking: bool) -> None:
        """Start new branch in repository and checkout

        :param str remote: Remote name
        :param str branch: Local branch name to create
        :param int depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer
        :param bool tracking: Whether to create a remote branch with tracking relationship
        """

        if branch not in self.repo.heads:
            if not is_offline():
                self.fetch(remote, ref=GitRef(branch=branch), depth=depth)
            try:
                self._create_branch_local(branch)
                self._checkout_branch_local(branch)
            except BaseException as err:
                LOG.debug('Failed to create and checkout branch', err)
                raise
        else:
            CONSOLE.stdout(f' - {fmt.ref(branch)} already exists')
            if self._is_branch_checked_out(branch):
                CONSOLE.stdout(' - On correct branch')
            else:
                self._checkout_branch_local(branch)

        if tracking and not is_offline():
            self._create_branch_remote_tracking(branch, remote, depth)
コード例 #16
0
ファイル: project_repo.py プロジェクト: JrGoodle/clowder
    def reset(self, depth: int = 0) -> None:
        """Reset branch to upstream or checkout tag/sha as detached HEAD

        :param int depth: Git clone depth. 0 indicates full clone, otherwise must be a positive integer
        :raise ClowderGitError:
        :raise UnknownTypeError:
        """

        if self.default_ref.ref_type is GitRefEnum.TAG:
            self.fetch(self.remote, ref=self.default_ref, depth=depth)
            self._checkout_tag(self.default_ref.short_ref)
        elif self.default_ref.ref_type is GitRefEnum.COMMIT:
            self.fetch(self.remote, ref=self.default_ref, depth=depth)
            self._checkout_sha(self.default_ref.short_ref)
        elif self.default_ref.ref_type is GitRefEnum.BRANCH:
            branch = self.default_ref.short_ref
            if not self.has_local_branch(branch):
                self._create_branch_local_tracking(branch, self.remote, depth=depth, fetch=True)
                return
            self._checkout_branch(branch)
            if not self.has_remote_branch(branch, self.remote):
                raise ClowderGitError(f'No existing remote branch {fmt.remote(self.remote)} {fmt.ref(branch)}')
            self.fetch(self.remote, ref=self.default_ref, depth=depth)
            CONSOLE.stdout(f' - Reset branch {fmt.ref(branch)} to {fmt.remote(self.remote)} {fmt.ref(branch)}')
            self._reset_head(branch=f'{self.remote}/{branch}')
        else:
            raise UnknownTypeError('Unknown GitRefEnum type')
コード例 #17
0
def config_set_protocol(args) -> None:
    """Clowder config set protocol command entry point"""

    CONSOLE.stdout(' - Set protocol config value')
    config = Config()
    config.protocol = GitProtocol(args.protocol[0])
    config.save()
コード例 #18
0
ファイル: resolved_project.py プロジェクト: JrGoodle/clowder
    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)
コード例 #19
0
ファイル: clowder_repo.py プロジェクト: JrGoodle/clowder
    def run_command(self, command: str) -> None:
        """Run command in clowder repo

        :param str command: Command to run
        """

        CONSOLE.stdout(fmt.command(command))
        execute_command(command.split(), self.repo_path)
コード例 #20
0
    def wrapper(*args, **kwargs):
        """Wrapper"""

        instance = args[0]
        if instance.is_detached:
            CONSOLE.stdout(' - HEAD is detached')
            return
        return func(*args, **kwargs)
コード例 #21
0
    def push(self) -> None:
        """Push changes"""

        try:
            CONSOLE.stdout(' - Push local changes')
            CONSOLE.stdout(self.repo.git.push())
        except GitError:
            LOG.error('Failed to push local changes')
            raise
コード例 #22
0
    def print_local_branches(self) -> None:
        """Print local git branches"""

        for branch in self.repo.git.branch().split('\n'):
            if branch.startswith('* '):
                branch_name = fmt.green(branch[2:])
                CONSOLE.stdout(f"* {branch_name}")
            else:
                CONSOLE.stdout(branch)
コード例 #23
0
    def install_lfs_hooks(self) -> None:
        """Install git lfs hooks"""

        CONSOLE.stdout(" - Update git lfs hooks")
        try:
            self.repo.git.lfs('install', '--local')
        except GitError:
            LOG.error('Failed to update git lfs hooks')
            raise
コード例 #24
0
    def pull(self) -> None:
        """Pull upstream changes"""

        try:
            CONSOLE.stdout(' - Pull latest changes')
            CONSOLE.stdout(self.repo.git.pull())
        except GitError:
            LOG.error('Failed to pull latest changes')
            raise
コード例 #25
0
    def pull_lfs(self) -> None:
        """Pull lfs files"""

        try:
            CONSOLE.stdout(' - Pull git lfs files')
            self.repo.git.lfs('pull')
        except GitError:
            LOG.error('Failed to pull git lfs files')
            raise
コード例 #26
0
    def stash(self) -> None:
        """Stash current changes in repository"""

        if not self.repo.is_dirty():
            CONSOLE.stdout(' - No changes to stash')
            return

        CONSOLE.stdout(' - Stash current changes')
        self.repo.git.stash()
コード例 #27
0
ファイル: resolved_project.py プロジェクト: JrGoodle/clowder
    def print_validation(self, allow_missing_repo: bool = True) -> None:
        """Print validation message for project

        :param bool allow_missing_repo: Whether to allow validation to succeed with missing repo
        """

        if not self.is_valid(allow_missing_repo=allow_missing_repo):
            CONSOLE.stdout(self.status())
            self.repo.print_validation()
コード例 #28
0
ファイル: project_repo.py プロジェクト: JrGoodle/clowder
    def install_project_git_herd_alias(self) -> None:
        """Install 'git herd' alias for project"""

        from clowder.environment import ENVIRONMENT

        config_variable = 'alias.herd'
        config_value = f'!clowder herd {self.repo_path.relative_to(ENVIRONMENT.clowder_dir)}'
        CONSOLE.stdout(" - Update git herd alias")
        self.git_config_unset_all_local(config_variable)
        self.git_config_add_local(config_variable, config_value)
コード例 #29
0
ファイル: checkout.py プロジェクト: JrGoodle/clowder
def checkout(args) -> None:
    """Clowder checkout command private implementation"""

    projects = Config().process_projects_arg(args.projects)
    projects = CLOWDER_CONTROLLER.filter_projects(CLOWDER_CONTROLLER.projects,
                                                  projects)

    for project in projects:
        CONSOLE.stdout(project.status())
        project.checkout(args.branch[0])
コード例 #30
0
    def print_validation(self) -> None:
        """Print validation messages"""

        if not existing_git_repo(self.repo_path):
            return

        if not self.validate_repo():
            CONSOLE.stdout(
                f'Dirty repo. Please stash, commit, or discard your changes')
            self.status_verbose()