Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single file checkout #143

Open
Shkurupii opened this issue Oct 17, 2019 · 1 comment
Open

Single file checkout #143

Shkurupii opened this issue Oct 17, 2019 · 1 comment

Comments

@Shkurupii
Copy link

Hello! Please advice how to check out one file inside big folder with the help of RemoteClient or anyhow else. Thanks!

@jfthuong
Copy link

jfthuong commented Dec 29, 2020

@Shkurupii You need to use depth, which is (currently) not implemented in the master branch.

I had the same issue and I have worked on a fork to do it.

While waiting for it to be merged and deployed to Pypi, below is the code I use.

The idea is:

  1. If you have nothing checked out yet, run "checkout --depth empty"
  2. Run recursively (for each subfolder that does not exist) the command update --depth empty
  3. Run update on the file you want to checkout
import xml.etree.ElementTree
from pathlib import Path
from typing import Union


import svn.common
import svn.constants
import svn.exception
import svn.local

PathLike = Union[str, Path]

# TODO: Remove when bug #96 and #169 have been integrated to PySvn
# IMPORT should be replaced by:
# from svn.local import LocalClient


def get_depth_options(depth, set_depth=False):
    """Get options for depth and check (set_depth=True for --set-depth)"""
    depth_values = {"empty", "files", "immediates", "infinity"}
    if set_depth:
        depth_values = depth_values.union({"exclude"})

    if depth not in depth_values:
        raise svn.exception.SvnException(
            "Invalid depth '{d}' (values allowed: {v})!".format(d=depth, v=depth_values)
        )

    return ["--set-depth" if set_depth else "--depth", depth]


class CommonClient(svn.common.CommonClient):
    """Improved version to be able to get schedule of file"""

    def get_schedule(self, rel_path=None):
        # To be replaced by lc.info(rel_path)["wcinfo_schedule"]
        cmd = []
        full_url_or_path = self.__url_or_path
        if rel_path is not None:
            full_url_or_path += "/" + rel_path
        cmd += ["--xml", full_url_or_path]
        result = self.run_command("info", cmd, do_combine=True)

        root = xml.etree.ElementTree.fromstring(result)
        node = root.find("entry/wc-info/schedule")
        return self.__element_text(node)


class LocalClient(svn.local.LocalClient):
    """Improved version of update to be able to set depth"""

    def update(
        self,
        rel_filepaths=[],
        revision=None,
        force=False,
        depth=None,
        set_depth=None,
        ignore_ext=False,
    ):
        cmd = []
        if revision is not None:
            cmd += ["-r", str(revision)]
        if force:
            cmd += ["--force"]
        if depth:
            cmd += get_depth_options(depth, set_depth=False)
        if set_depth:
            cmd += get_depth_options(set_depth, set_depth=True)
        if ignore_ext:
            cmd += ["--ignore-externals"]

        cmd += rel_filepaths
        self.run_command("update", cmd, wd=self.path)


# TODO: --- END REMOVE


def update_path(
    lc: LocalClient,
    path: PathLike,
    revision: int = None,
    set_depth: str = None,
    root: PathLike = None,
):
    """Update a path with the parents being empty (unless they were present before)"""
    root = Path(root or "")
    rel_path = Path(path).relative_to(root)
    missing_parents = [
        str(p) for p in reversed(rel_path.parents) if not (root / p).is_dir()
    ]
    if missing_parents:
        lc.update(missing_parents, set_depth="empty")
    lc.update([str(rel_path)], revision=revision, set_depth=set_depth)


root = Path("my_project")
lc = LocalClient(str(root))
lc.update(set_depth="empty")
path = root / "branches" / "my_branch1"
update_path(lc, path, set_depth="files", root=root)
path = Path("my_project/branches/a")
update_path(lc, path, set_depth="files", root=root)
lc.update()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants