Rsync¶
- class rmote.tools.rsync.Rsync[source]¶
Bases:
ToolSynchronize the contents of a directory into another directory.
Call upload/download directly with an open async Protocol. Both directions use the same traversal and compare every regular file through FileSync, even when size and mtime match. A trailing slash has no special meaning. Empty directories and symbolic links (including dangling links) are copied. Links are never traversed. Type conflicts and special source files raise ValueError. Extra destination entries are retained unless delete=True.
Exclusions are case-sensitive globs over relative POSIX paths. A pattern without a slash matches an entry name at any depth (
*.pyc,.git/). A leading slash anchors to the root (/cache/); other patterns containing slashes are also root-relative (build/**).*,?and[abc]match within one component; a whole**component matches zero or more components. A trailing slash matches directories only, not symlinks. Patterns have no negation or ordering rules: any match excludes the path. For example,exclude=(".git/", "__pycache__/", "*.pyc", "build/**"). Excluded directories are not traversed. Excluded destination entries and their necessary parents survive delete=True, including in destination-only subtrees. Their contents, modes and ownership are left untouched.Transfers are atomic per file, not per tree. Deletion starts only after all content transfers succeed. On failure, completed changes remain; retry to converge. Keep both trees stable and non-overlapping during synchronization; this is not a filesystem snapshot or protection against concurrent renames. Root paths and their parents must not be symbolic links. The destination’s parent must exist; the destination root itself may be absent.
preserve_mode copies permission bits, including executable bits, applying directory modes last. Owners, timestamps, ACLs, xattrs and hard-link identity are not copied. With preserve_mode=False, FileSync’s metadata policy applies to files; new directories use 0700 and existing directory modes are kept. Existing destination directories must be writable for changed contents. owner/group optionally set destination ownership (names resolved there), including symlinks themselves. Without them, no ownership change is requested; new entries use the creating process and destination directory defaults. No external rsync executable is needed.
Example with a real local subprocess:
>>> import asyncio >>> import sys >>> from tempfile import TemporaryDirectory >>> from rmote.protocol import Protocol >>> async def example(): ... with TemporaryDirectory() as directory: ... root = Path(directory).resolve() ... source, target = root / "source", root / "target" ... source.mkdir() ... (source / "hello.txt").write_text("hello") ... (source / ".git").mkdir() ... (source / ".git" / "config").write_text("local only") ... process = await asyncio.create_subprocess_exec( ... sys.executable, "-qui", stdin=asyncio.subprocess.PIPE, ... stdout=asyncio.subprocess.PIPE, ... ) ... try: ... async with await Protocol.from_subprocess(process) as protocol: ... first = await Rsync.upload(protocol, source, target, exclude=(".git/",)) ... again = await Rsync.upload(protocol, source, target, exclude=(".git/",)) ... assert not (target / ".git").exists() ... return first.changed, again.changed, (target / "hello.txt").read_text() ... finally: ... if process.returncode is None: ... process.terminate() ... await process.wait() >>> asyncio.run(example()) (True, False, 'hello')
- static chown(path, uid, gid)[source]¶
Apply explicit ownership to the entry itself, including symlinks.
- Return type:
- async static download(protocol, remote_path, local_path, *, delete=False, concurrency=4, preserve_mode=True, block_size=1048576, owner=None, group=None, exclude=())[source]¶
Copy remote directory contents into a local directory.
- Parameters:
protocol (
Callable[...,Awaitable[Any]]) – Open async Protocol, already entered with async with.remote_path (
Text|Path) – Source directory, relative to the remote cwd.local_path (
Text|Path) – Destination directory, relative to the local cwd.delete (
bool) – Remove destination-only entries after successful transfers.concurrency (
getint) – Maximum simultaneous file transfers (positive integer).preserve_mode (
bool) – Copy source file and directory permission bits.block_size (
getint) – FileSync block size, between 1 byte and 16 MiB.owner (
Text|None) – Explicit destination username; None keeps normal ownership.group (
Text|None) – Explicit destination group name; None keeps normal grouping.exclude (
Iterable[Text]) – Glob patterns for paths to leave untouched on both sides. See Rsync for matching and deletion rules.
- Return type:
- Returns:
Aggregate change status and transfer counters.
Uses the same error, deletion and metadata policy as upload.
- static excluded(relative, kind, patterns)[source]¶
Match a root-relative POSIX path without consulting the filesystem.
- Return type:
- static inspect(path)[source]¶
Inspect a single entry without dereferencing it; None means absent.
- Return type:
Entry|None
- static link(path, target)[source]¶
Create or atomically replace a link; refuse other existing types.
- Return type:
- static ownership(owner, group)[source]¶
Resolve explicitly requested names on the destination host.
- Return type:
tuple[getint,getint]
- static remove(path, relative='', patterns=())[source]¶
Remove extra entries, retaining excluded descendants and their parents.
- Return type:
getint
- static root(path, required)[source]¶
Validate and normalize a root, rejecting symlink path components.
- Return type:
- static scan(path)[source]¶
Read one directory, without following links or scanning descendants.
- Return type:
WSGIEnvironment[Text,Entry]
- async static transfer(protocol, local_path, remote_path, uploading, delete, concurrency, preserve_mode, block_size, owner, group, exclude)[source]¶
Shared local coordinator for both directions.
- Return type:
- async static upload(protocol, local_path, remote_path, *, delete=False, concurrency=4, preserve_mode=True, block_size=1048576, owner=None, group=None, exclude=())[source]¶
Copy local directory contents into a remote directory.
- Parameters:
protocol (
Callable[...,Awaitable[Any]]) – Open async Protocol, already entered with async with.local_path (
Text|Path) – Source directory, relative to the local cwd.remote_path (
Text|Path) – Destination directory, relative to the remote cwd.delete (
bool) – Remove destination-only entries after successful transfers.concurrency (
getint) – Maximum simultaneous file transfers (positive integer).preserve_mode (
bool) – Copy source file and directory permission bits.block_size (
getint) – FileSync block size, between 1 byte and 16 MiB.owner (
Text|None) – Explicit destination username; None keeps normal ownership.group (
Text|None) – Explicit destination group name; None keeps normal grouping.exclude (
Iterable[Text]) – Glob patterns for paths to leave untouched on both sides. See Rsync for matching and deletion rules.
- Return type:
- Returns:
Aggregate change status and transfer counters.
- Raises:
ValueError – Invalid options, unsupported source type, type conflict, or a symbolic link in a root path.
OSError – A filesystem operation fails.
RuntimeError – FileSync detects a file changing during transfer.
ConnectionError – The remote connection fails.
asyncio.CancelledError – Cancelled after active operations settle.
Types¶
- class rmote.tools.rsync.Result(changed=False, files=0, transferred=0, reused=0, directories=0, symlinks=0, deleted=0)[source]¶
Bases:
objectCompleted directory synchronization, including content and mode changes.
- changed¶
Whether any destination entry or permission changed.
- files¶
Number of regular files checked through FileSync.
- transferred¶
File content bytes sent; excludes RPC and signatures.
- reused¶
File content bytes reused from the destination.
- directories¶
Number of directories created, including the root.
- symlinks¶
Number of symbolic links created or replaced.
- deleted¶
Number of extra entries removed, including nested entries.