This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-releases-client.git


The following commit(s) were added to refs/heads/main by this push:
     new 85b1e49  Add an rsync wrapper command
85b1e49 is described below

commit 85b1e49a5931c942226ef65ed82d8a775253c767
Author: Sean B. Palmer <s...@miscoranda.com>
AuthorDate: Wed Jul 23 20:44:37 2025 +0100

    Add an rsync wrapper command
---
 pyproject.toml          |  4 ++--
 src/atrclient/client.py | 28 ++++++++++++++++++++++++++++
 uv.lock                 | 16 ++++++++--------
 3 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index d0c7d6e..d881a2c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ build-backend = "hatchling.build"
 
 [project]
 name            = "apache-trusted-releases"
-version         = "0.20250720.1045"
+version         = "0.20250723.1944"
 description     = "ATR CLI and Python API"
 readme          = "README.md"
 requires-python = ">=3.13"
@@ -72,4 +72,4 @@ select = [
 ]
 
 [tool.uv]
-exclude-newer = "2025-07-20T10:45:00Z"
+exclude-newer = "2025-07-23T19:44:00Z"
diff --git a/src/atrclient/client.py b/src/atrclient/client.py
index b273c4d..06e6c50 100755
--- a/src/atrclient/client.py
+++ b/src/atrclient/client.py
@@ -710,6 +710,34 @@ def app_revisions(project: str, version: str, /) -> None:
         print(revision)
 
 
+@APP.command(name="rsync", help="Rsync a release.")
+def app_rsync(project: str, version: str, source: str = ".", target: str = 
"/", /) -> None:
+    import subprocess
+
+    with config_lock() as config:
+        asf_uid = config_get(config, ["asf", "uid"])
+    if asf_uid is None:
+        show_error_and_exit("Please configure asf.uid before uploading.")
+
+    if not source.endswith("/"):
+        source += "/"
+
+    if target.startswith("./"):
+        target = target[2:]
+    elif target.startswith("/"):
+        target = target[1:]
+    if target and (not target.endswith("/")):
+        # Must not do this if target is empty
+        target += "/"
+
+    host, _verify_ssl = config_host_get()
+    if ":" in host:
+        host, _port = host.split(":", 1)
+    remote_target = f"{asf_uid}@{host}:/{project}/{version}/{target}"
+    cmd = ["rsync", "-av", "-e", "ssh -p 2222", source, remote_target]
+    subprocess.run(cmd, check=True)
+
+
 @APP.command(name="set", help="Set a configuration value using dot notation.")
 def app_set(path: str, value: str, /) -> None:
     parts = path.split(".")
diff --git a/uv.lock b/uv.lock
index 0aa7d80..1b14201 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,7 +2,7 @@ version = 1
 requires-python = ">=3.13"
 
 [options]
-exclude-newer = "2025-07-20T10:45:00Z"
+exclude-newer = "2025-07-23T19:44:00Z"
 
 [[package]]
 name = "aiohappyeyeballs"
@@ -83,7 +83,7 @@ wheels = [
 
 [[package]]
 name = "apache-trusted-releases"
-version = "0.20250720.1045"
+version = "0.20250723.1944"
 source = { editable = "." }
 dependencies = [
     { name = "aiohttp" },
@@ -181,11 +181,11 @@ wheels = [
 
 [[package]]
 name = "docstring-parser"
-version = "0.16"
+version = "0.17.0"
 source = { registry = "https://pypi.org/simple"; }
-sdist = { url = 
"https://files.pythonhosted.org/packages/08/12/9c22a58c0b1e29271051222d8906257616da84135af9ed167c9e28f85cb3/docstring_parser-0.16.tar.gz";,
 hash = 
"sha256:538beabd0af1e2db0146b6bd3caa526c35a34d61af9fd2887f3a8a27a739aa6e", size 
= 26565 }
+sdist = { url = 
"https://files.pythonhosted.org/packages/b2/9d/c3b43da9515bd270df0f80548d9944e389870713cc1fe2b8fb35fe2bcefd/docstring_parser-0.17.0.tar.gz";,
 hash = 
"sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", size 
= 27442 }
 wheels = [
-    { url = 
"https://files.pythonhosted.org/packages/d5/7c/e9fcff7623954d86bdc17782036cbf715ecab1bec4847c008557affe1ca8/docstring_parser-0.16-py3-none-any.whl";,
 hash = 
"sha256:bf0a1387354d3691d102edef7ec124f219ef639982d096e26e3b60aeffa90637", size 
= 36533 },
+    { url = 
"https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl";,
 hash = 
"sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708", size 
= 36896 },
 ]
 
 [[package]]
@@ -693,16 +693,16 @@ wheels = [
 
 [[package]]
 name = "virtualenv"
-version = "20.31.2"
+version = "20.32.0"
 source = { registry = "https://pypi.org/simple"; }
 dependencies = [
     { name = "distlib" },
     { name = "filelock" },
     { name = "platformdirs" },
 ]
-sdist = { url = 
"https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz";,
 hash = 
"sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size 
= 6076316 }
+sdist = { url = 
"https://files.pythonhosted.org/packages/a9/96/0834f30fa08dca3738614e6a9d42752b6420ee94e58971d702118f7cfd30/virtualenv-20.32.0.tar.gz";,
 hash = 
"sha256:886bf75cadfdc964674e6e33eb74d787dff31ca314ceace03ca5810620f4ecf0", size 
= 6076970 }
 wheels = [
-    { url = 
"https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl";,
 hash = 
"sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size 
= 6057982 },
+    { url = 
"https://files.pythonhosted.org/packages/5c/c6/f8f28009920a736d0df434b52e9feebfb4d702ba942f15338cb4a83eafc1/virtualenv-20.32.0-py3-none-any.whl";,
 hash = 
"sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56", size 
= 6057761 },
 ]
 
 [[package]]


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@tooling.apache.org
For additional commands, e-mail: commits-h...@tooling.apache.org

Reply via email to