Ejemplo n.º 1
0
 def pull(self,
          remote: Optional[str] = None,
          branch: Optional[str] = None,
          rebase: bool = False,
          prune: bool = False,
          tags: bool = False,
          jobs: Optional[int] = None,
          no_edit: bool = False,
          autostash: bool = False,
          depth: Optional[int] = None) -> None:
     # TODO: Check if detached
     message = f' - Pull'
     if rebase:
         message += ' with rebase'
     CONSOLE.stdout(message)
     GitOnline.pull(self.path,
                    remote=remote,
                    branch=branch,
                    rebase=rebase,
                    prune=prune,
                    tags=tags,
                    jobs=jobs,
                    no_edit=no_edit,
                    autostash=autostash,
                    depth=depth)
Ejemplo n.º 2
0
 def checkout(self, check: bool = True, track: bool = False) -> None:
     current_commit = GitOffline.current_head_commit_sha(self.path)
     if current_commit == self.sha:
         CONSOLE.stdout(' - On correct commit for tag')
         return
     CONSOLE.stdout(f' - Checkout tag {self.name}')
     super().checkout(check=check, track=track)
Ejemplo n.º 3
0
 def checkout(self, ref: str, track: bool = False) -> None:
     if self.is_dirty:
         CONSOLE.stdout(
             ' - Dirty repo. Please stash, commit, or discard your changes')
         self.status(verbose=True)
         return
     GitOffline.checkout(self.path, ref=ref, track=track)
Ejemplo n.º 4
0
 def fetch(self,
           prune: bool = False,
           prune_tags: bool = False,
           tags: bool = False,
           depth: Optional[int] = None,
           remote: Optional[str] = None,
           branch: Optional[str] = None,
           unshallow: bool = False,
           jobs: Optional[int] = None,
           fetch_all: bool = False,
           check: bool = True,
           print_output: bool = True):
     # FIXME: Consolidate this implementation with the one for Remotes
     CONSOLE.stdout(f' - Fetch repo')
     try:
         GitOnline.fetch(self.path,
                         remote=remote,
                         prune=prune,
                         prune_tags=prune_tags,
                         tags=tags,
                         depth=depth,
                         branch=branch,
                         unshallow=unshallow,
                         jobs=jobs,
                         fetch_all=fetch_all,
                         print_output=print_output)
     except Exception:  # noqa
         message = f'Failed to fetch repo'
         if check:
             GIT_LOG.error(message)
             raise
         CONSOLE.stdout(message)
Ejemplo n.º 5
0
 def reset(self, ref: Union[Ref, str] = HEAD, hard: bool = False) -> None:
     if isinstance(ref, TrackingBranch):
         ref = ref.upstream_branch.short_ref
     elif isinstance(ref, Ref):
         ref = ref.short_ref
     CONSOLE.stdout(f' - Reset repo to {Format.Git.ref(ref)}')
     GitOffline.reset(self.path, ref=ref, hard=hard)
Ejemplo n.º 6
0
 def wrapper(*args, **kwargs):
     if isinstance(message, Callable):
         instance = args[0]
         msg: str = message(instance)
     else:
         msg: str = str(message)
     CONSOLE.stdout(msg)
     return func(*args, **kwargs)
Ejemplo n.º 7
0
    def print_validation(self, allow_missing: bool = False) -> None:
        """Print validation message"""

        if not self.exists or self.is_valid(allow_missing=allow_missing):
            return
        self.status()
        CONSOLE.stdout(
            f'Dirty repo. Please stash, commit, or discard your changes')
Ejemplo n.º 8
0
    def print_local_branches(self) -> None:
        """Print local git branches"""

        for branch in self.get_local_branches():
            if branch.name == self.current_branch:
                CONSOLE.stdout(f'* {Format.green(branch.name)}')
            else:
                CONSOLE.stdout(branch)
Ejemplo n.º 9
0
 def checkout(self, check: bool = True, track: bool = False) -> None:
     current_commit = GitOffline.current_head_commit_sha(self.path)
     # TODO: Should this always check out detached HEAD?
     if current_commit == self.sha and GitOffline.is_detached(self.path):
         CONSOLE.stdout(' - On correct commit')
         return
     CONSOLE.stdout(f' - Checkout commit {Format.Git.ref(self.short_ref)}')
     super().checkout(check=check, track=track)
Ejemplo n.º 10
0
    def wrapper(*args, **kwargs):
        """Wrapper"""

        instance = args[0]
        if GitOffline.is_detached(instance.path):
            CONSOLE.stdout(' - HEAD is detached')
            raise Exception('Detached HEAD')
        return func(*args, **kwargs)
Ejemplo n.º 11
0
 def checkout(self, check: bool = True, track: bool = False) -> None:
     current_branch = GitOffline.current_branch(self.path)
     if current_branch == self.name:
         CONSOLE.stdout(
             f' - Branch {Format.Git.ref(self.short_ref)} already checked out'
         )
         return
     CONSOLE.stdout(f' - Checkout branch {Format.Git.ref(self.short_ref)}')
     super().checkout(check=check, track=track)
Ejemplo n.º 12
0
 def reset_timestamp(self,
                     timestamp: str,
                     ref: Ref,
                     author: Optional[str] = None) -> None:
     CONSOLE.stdout(' - Reset timestamp')
     GitOffline.reset_timestamp(self.path,
                                timestamp=timestamp,
                                ref=ref.short_ref,
                                author=author)
Ejemplo n.º 13
0
 def checkout(self, check: bool = True, track: bool = False) -> None:
     try:
         GitOffline.checkout(self.path, ref=self.short_ref, track=track)
     except Exception:  # noqa
         message = f'Failed to checkout'
         if check:
             GIT_LOG.error(message)
             raise
         CONSOLE.stdout(f' - {message}')
Ejemplo n.º 14
0
 def push(self, remote: Optional[str] = None, branch: Optional[str] = None,
          force: bool = False, set_upstream: bool = False) -> None:
     # TODO: Check if detached
     CONSOLE.stdout(' - Push local changes')
     GitOnline.push(self.path,
                    local_branch=self.name,
                    remote_branch=branch,
                    remote=remote,
                    force=force,
                    set_upstream=set_upstream)
Ejemplo n.º 15
0
    def update_git_config(self, config: GitConfig) -> None:
        """Update custom git config

        :param GitConfig config: Custom git config
        """

        CONSOLE.stdout(" - Update local git config")
        for key, value in config.items():
            GitOffline.git_config_unset_all_local(self.path, key)
            GitOffline.git_config_add_local(self.path, key, value)
Ejemplo n.º 16
0
 def set_upstream(self) -> None:
     CONSOLE.stdout(
         f' - Set tracking branch {Format.Git.ref(self.name)} -> '
         f'{Format.Git.remote(self.upstream_branch.remote.name)} '
         f'{Format.Git.ref(self.upstream_branch.name)}')
     GitOffline.set_upstream_branch(
         self.path,
         local_branch=self.name,
         upstream_branch=self.upstream_branch.name,
         remote=self.upstream_branch.remote.name)
Ejemplo n.º 17
0
    def add(self, files: Union[Path, str, List[str], List[Path]]) -> None:
        if isinstance(files, str):
            files = [files]
        elif isinstance(files, Path):
            files = [str(files)]
        elif isinstance(files, list):
            files = [str(f) for f in files]
        else:
            raise Exception('Wrong type for files parameter')

        CONSOLE.stdout(' - Add files to git index')
        GitOffline.add(self.path, files=files)
Ejemplo n.º 18
0
 def delete(self) -> None:
     if not self.exists:
         CONSOLE.stdout(
             f" - Remote tag {Format.Git.ref(self.short_ref)} doesn't exist"
         )
         return
     CONSOLE.stdout(
         f' - Delete remote tag {Format.Git.ref(self.short_ref)}')
     GitOnline.delete_remote_tag(self.path,
                                 tag=self.name,
                                 remote=self.remote.name,
                                 force=True)
Ejemplo n.º 19
0
 def delete(self) -> None:
     from pygoodle.git.model.factory import GitFactory
     if not GitFactory.has_remote_branch_online(self.path, self.name,
                                                self.remote.name):
         CONSOLE.stdout(
             f" - Remote branch {Format.Git.ref(self.name)} doesn't exist")
         return
     CONSOLE.stdout(f' - Delete remote branch {Format.Git.ref(self.name)}')
     GitOnline.delete_remote_branch(self.path,
                                    branch=self.name,
                                    remote=self.remote.name,
                                    force=True)
Ejemplo n.º 20
0
 def clone(self,
           path: Path,
           url: str,
           depth: Optional[int] = None,
           branch: Optional[str] = None,
           jobs: Optional[int] = None,
           origin: Optional[str] = None) -> 'Repo':
     CONSOLE.stdout(' - Clone repo')
     GitOnline.clone(path,
                     url=url,
                     depth=depth,
                     branch=branch,
                     jobs=jobs,
                     origin=origin)
     return Repo(path)
Ejemplo n.º 21
0
    def save(self, contents: dict) -> None:
        """Save yaml file to disk

        :param dict contents: Parsed YAML python object
        :raise ExistingFileError:
        """

        if self.path.is_file():
            raise ExistingFileError(f"File already exists: {Format.path(self.path)}")

        CONSOLE.stdout(f" - Save yaml to file at {Format.path(self.path)}")
        try:
            with self.path.open(mode="w") as raw_file:
                pyyaml.safe_dump(contents, raw_file, default_flow_style=False, indent=2, sort_keys=False)
        except pyyaml.YAMLError:
            # LOG.error(f"Failed to save file {Format.path(yaml_file)}")
            raise
Ejemplo n.º 22
0
 def create(self, branch: Optional[str] = None, remote: Optional[str] = None, track: bool = True) -> None:
     if self.exists:
         CONSOLE.stdout(f' - Local branch {Format.Git.ref(self.short_ref)} already exists')
         return
     CONSOLE.stdout(f' - Create local branch {Format.Git.ref(self.short_ref)}')
     if branch is not None:
         if remote is not None:
             from pygoodle.git.model.branch.remote_branch import RemoteBranch
             remote_branch = RemoteBranch(self.path, branch, remote)
             if not remote_branch.exists:
                 branch = None
                 remote = None
         else:
             local_branch = LocalBranch(self.path, branch)
             if not local_branch.exists:
                 branch = None
     GitOffline.create_local_branch(self.path, self.name, branch=branch, remote=remote, track=track)
Ejemplo n.º 23
0
    def download(self, path: Path) -> Path:
        file_type = self._file_type(path)
        if file_type is FileType.FILE:
            files = [FileInfo(path, self._get_file_size(path))]
        elif file_type is FileType.DIR:
            with self.reserve_ftp() as ftp:
                directory_info = DirectoryInfo(ftp, path)
            self._make_download_dirs(path, directory_info)
            files = directory_info.files
        else:
            raise Exception('Unknown file type')

        download_path = self._get_download_path(path)

        class DownloadTaskPool(ProgressTaskPool):
            def after_tasks(self, tasks: List[ProgressTask]) -> None:
                super().after_tasks(tasks)
                if self.cancelled:
                    CONSOLE.stdout(f'Remove {download_path}', force=True)
                    fs.remove(download_path)

        ftp = self

        class DownloadTask(ProgressTask):
            def __init__(self, file: FileInfo):
                super().__init__(file.name, units='bytes', total=file.size)
                self._file: FileInfo = file

            def run(self) -> None:
                def callback(data):
                    if self.cancelled:
                        raise CancelledDownloadError(
                            f'FTP download of {self._file.name} was cancelled')
                    self.progress.update_subtask(self._file.name,
                                                 advance=len(data))

                ftp.download_file(self._file, callback)

        download_tasks = [DownloadTask(file) for file in files]
        pool = DownloadTaskPool(jobs=self.pool_size,
                                title='Files',
                                units='files')
        pool.run(download_tasks)
        CONSOLE.stdout(f'Downloaded {len(files)} files', force=True)
        return download_path
Ejemplo n.º 24
0
 def fetch(self, prune: bool = False, prune_tags: bool = False, tags: bool = False,
           depth: Optional[int] = None, branch: Optional[str] = None, unshallow: bool = False,
           jobs: Optional[int] = None, fetch_all: bool = False, check: bool = True,
           print_output: bool = True) -> None:
     output = self.name
     if branch is not None:
         branch = branch
         output = f'{output} {branch}'
     CONSOLE.stdout(f'Fetch from {output}')
     try:
         GitOnline.fetch(self.path, remote=self.name, prune=prune, prune_tags=prune_tags, tags=tags, depth=depth,
                         branch=branch, unshallow=unshallow, jobs=jobs, fetch_all=fetch_all, print_output=print_output)
     except Exception:  # noqa
         message = f'Failed to fetch from {output}'
         if check:
             GIT_LOG.error(message)
             raise
         CONSOLE.stdout(f' - {message}')
Ejemplo n.º 25
0
    def clean(self,
              untracked_directories: bool = False,
              force: bool = False,
              ignored: bool = False,
              untracked_files: bool = False) -> None:
        """Discard changes for repo

        :param bool untracked_directories: ``d`` Remove untracked directories in addition to untracked files
        :param bool force: ``f`` Delete directories with .git sub directory or file
        :param bool ignored: ``X`` Remove only files ignored by git
        :param bool untracked_files: ``x`` Remove all untracked files
        """

        CONSOLE.stdout(' - Clean repo')
        GitOffline.clean(self.path,
                         untracked_directories=untracked_directories,
                         force=force,
                         ignored=ignored,
                         untracked_files=untracked_files)
Ejemplo n.º 26
0
 def create(self,
            branch: Optional[str] = None,
            remote: Optional[str] = None) -> None:
     from pygoodle.git.model.factory import GitFactory
     if GitFactory.has_remote_branch_online(self.path, self.name,
                                            self.remote.name):
         CONSOLE.stdout(
             f' - Remote branch {Format.Git.ref(self.name)} already exists')
         return
     CONSOLE.stdout(f' - Create remote branch {Format.Git.ref(self.name)}')
     branch = self.name if branch is None else branch
     from pygoodle.git.model.branch.local_branch import LocalBranch
     local_branch = LocalBranch(self.path, branch)
     GitOnline.fetch(self.path, prune=True)
     has_existing_branch = local_branch.exists
     if not has_existing_branch:
         local_branch.create(branch=branch, remote=remote)
     local_branch.push(remote=self.remote.name, branch=self.name)
     if not has_existing_branch:
         GitOffline.delete_local_branch(self.path, branch)
     GitOnline.fetch(self.path, prune=True)
Ejemplo n.º 27
0
    def create(self) -> None:
        if GitOffline.has_tracking_branch(self.path, self.local_branch.name):
            CONSOLE.stdout(' - Tracking branch already exists')
            return
        # TODO: Add Format util to format tracking branch output: local_branch -> remote remote_branch
        CONSOLE.stdout(
            f' - Create tracking branch {Format.Git.ref(self.name)}')
        GitOnline.fetch(self.path, prune=True)
        # local and remote branches exist
        if self.local_branch.exists and self.upstream_branch.exists:
            self.set_upstream()
            return

        # only local branch exists
        if self.local_branch.exists:
            # GitOnline.push(self.path,
            #                local_branch=self.name,
            #                remote_branch=self.upstream_branch.name,
            #                remote=self.upstream_branch.remote.name,
            #                set_upstream=True)
            self.upstream_branch.create(branch=self.local_branch.name)
            self.set_upstream()
            GitOnline.fetch(self.path, prune=True)
            return

        # only remote branch exists
        if self.upstream_branch.exists:
            self.local_branch.create(branch=self.upstream_branch.name,
                                     remote=self.upstream_branch.remote.name)
            # GitOffline.create_local_branch(self.path, self.name,
            #                                branch=self.upstream_branch.name,
            #                                remote=self.upstream_branch.remote)
            return

        # local and remote branches DO NOT exist
        self.upstream_branch.create()
        GitOnline.fetch(self.path, prune=True)
        self.local_branch.create(branch=self.upstream_branch.name,
                                 remote=self.upstream_branch.remote.name)
Ejemplo n.º 28
0
 def submodule_update(self,
                      init: bool = False,
                      depth: Optional[int] = None,
                      single_branch: bool = False,
                      jobs: Optional[int] = None,
                      recursive: bool = False,
                      remote: bool = False,
                      checkout: bool = False,
                      rebase: bool = False,
                      merge: bool = False,
                      paths: Optional[List[Path]] = None) -> None:
     CONSOLE.stdout(' - Update submodules')
     GitOnline.submodule_update(self.path,
                                init=init,
                                depth=depth,
                                single_branch=single_branch,
                                jobs=jobs,
                                recursive=recursive,
                                remote=remote,
                                checkout=checkout,
                                merge=merge,
                                rebase=rebase,
                                paths=paths)
Ejemplo n.º 29
0
 def create(self) -> None:
     if self.exists:
         CONSOLE.stdout(
             f' - Remote tag {Format.Git.ref(self.name)} already exists')
         return
     raise NotImplementedError
Ejemplo n.º 30
0
 def delete(self) -> None:
     if not self.exists:
         CONSOLE.stdout(f" - Local tag {Format.Git.ref(self.short_ref)} doesn't exist")
         return
     CONSOLE.stdout(f' - Delete local tag {Format.Git.ref(self.short_ref)}')
     GitOffline.delete_local_tag(self.path, name=self.name)