Skip to main content

CLI tool for syncing files with Polarion SVN when direct SVN access is not available

Project description

Polarion SVN CLI (svncli)

CI Python 3.10+ License: MIT

CLI tool for syncing files with Polarion's SVN repository when direct SVN access is not available — such as on PolarionX or other hosted environments.

Supports macOS, Linux, and Windows.

Why?

Some Polarion deployments don't expose direct SVN access. You can browse and manage individual files through the web UI, but there's no built-in way to recursively upload folders, sync changes, or automate file management. svncli fills that gap.

Installation

pip install svncli

For interactive browser login (optional):

pip install "svncli[interactive]"
playwright install chromium

From source

git clone https://github.com/pupca/svncli.git
cd svncli
pip install -e ".[dev]"

Quick start

1. Authenticate

Pick one of these methods:

# Auto-extract cookies from Chrome (requires being logged in via browser)
svncli login https://your-server.example.com

# Interactive login — opens a browser window (works with SSO/MFA)
svncli login -i https://your-server.example.com

# Manual cookie — paste from browser DevTools
svncli login --cookie "JSESSIONID=ABC123; X-CSRF-Token=DEF456" https://your-server.example.com

All methods save the session to ~/.svncli/cookies.json — you only need to log in once per server. After that, all commands just work.

2. Browse

svncli ls https://your-server.example.com:MyProject/trunk
svncli ls -r https://your-server.example.com:MyProject/trunk   # recursive

3. Copy files

# Upload
svncli cp ./report.pdf https://your-server.example.com:MyProject/trunk/docs/report.pdf

# Download
svncli cp https://your-server.example.com:MyProject/trunk/docs/report.pdf ./report.pdf

# Copy a whole folder
svncli cp -r ./local-folder https://your-server.example.com:MyProject/trunk/folder

4. Sync

# Push local changes to remote
svncli sync ./src https://your-server.example.com:MyProject/trunk/src

# Pull remote changes to local
svncli sync https://your-server.example.com:MyProject/trunk/src ./src

# Preview what would change
svncli sync -n ./src https://your-server.example.com:MyProject/trunk/src

# Delete remote files not present locally
svncli sync --delete --force ./src https://your-server.example.com:MyProject/trunk/src

5. Cross-server operations

Copy or sync files directly between two Polarion servers — no manual download/upload needed:

# Copy a folder from one server to another
svncli cp -r https://server1.com:Project/src https://server2.com:Project/src

# Sync between servers (only transfers changed files)
svncli sync https://server1.com:Project/src https://server2.com:Project/src

# Preview cross-server sync
svncli sync -n https://server1.com:Project/src https://server2.com:Project/src

This works by downloading from the source server to a temp directory, then uploading to the destination. Each server authenticates independently — run svncli login for each one.

Python API

svncli can be used as a Python library:

from svncli import PolarionSVNClient

client = PolarionSVNClient(verify_ssl=False)

# Authenticate (saved to ~/.svncli/cookies.json)
client.login("https://server.com")                            # auto-extract from Chrome
client.login("https://server.com", browser="edge")            # specific browser
client.login("https://server.com", cookie="JSESSIONID=...")   # manual cookie
client.login("https://server.com", interactive=True)           # opens browser window

# List files
items = client.ls("https://server.com:Project/trunk")
for item in items:
    print(f"{item.name}  {item.size} bytes  r{item.revision}")

# Copy a single file
client.cp("./report.pdf", "https://server.com:Project/docs/report.pdf")   # upload
client.cp("https://server.com:Project/docs/report.pdf", "./report.pdf")   # download

# Copy a directory recursively
actions = client.cp_r("./src", "https://server.com:Project/trunk/src")

# Sync with options
actions = client.sync("./src", "https://server.com:Project/trunk/src",
    delete=True,                     # remove remote files not in local
    exclude=["*.log", ".git/*"],     # exclude patterns
    dry_run=True,                    # preview only, don't execute
)

# Inspect what happened
from svncli import SyncOp
uploaded = [a for a in actions if a.op == SyncOp.UPLOAD]
skipped = [a for a in actions if a.op == SyncOp.SKIP]

# Cross-server sync
client.login("https://other-server.com")
client.sync("https://server.com:Project/src", "https://other-server.com:Project/src")

# Create / delete
client.mkdir("https://server.com:Project/new-folder")   # returns True
client.rm("https://server.com:Project/old-file.txt")     # returns True

Path format

Remote paths include the server URL followed by : and the repository path:

https://server.example.com:RepoName/folder/path

Local paths start with /, ./, or ~/:

./local-folder
/absolute/path
~/home-relative

Commands

Command Description
svncli ls <remote> List remote directory (-r for recursive)
svncli cp <src> <dst> Copy files (local↔remote or remote↔remote with -r)
svncli sync <src> <dst> Sync files between local and remote
svncli rm <remote> Delete a remote file or folder
svncli mb <remote> Create a remote directory
svncli login <server> Authenticate and save session cookies
svncli logout [server] Remove saved session cookies

Global options

--no-verify-ssl    Disable SSL certificate verification
--timeout SECONDS  HTTP request timeout (default: 60)
-v, --verbose      Verbose output
--version          Show version

Sync options

-n, --dry-run      Show what would change without doing it
--delete           Remove destination files not present in source
--force            Skip confirmation prompt for deletions
--exclude PATTERN  Exclude files matching glob pattern (repeatable)

Authentication

Each server has its own saved session. svncli resolves cookies per server in this order:

  1. --cookie flag
  2. Saved cookies from ~/.svncli/cookies.json (from a previous svncli login)
  3. Auto-extraction from browser cookie store (Chrome, Firefox, Edge, Safari, etc.)

Automatic cookie extraction

By default, svncli reads cookies from your Chrome cookie store. This requires that you've already logged into Polarion in Chrome. To use a different browser:

svncli login --browser firefox https://your-server.com
svncli login --browser edge https://your-server.com    # common on Windows

Supported browsers: chrome, firefox, edge, brave, opera, chromium, vivaldi, safari, librewolf, arc.

Interactive login

For environments where automatic cookie extraction doesn't work (e.g., remote servers, locked-down browsers):

svncli login -i https://your-server.com

This opens a Chromium window. Log in normally (including SSO/MFA), then close the window. Cookies are saved automatically.

Requires the interactive extra: pip install "svncli[interactive]" and playwright install chromium.

Manual cookie extraction

If neither automatic nor interactive login works, you can extract cookies manually from your browser:

  1. Open your Polarion server in Chrome/Firefox
  2. Log in normally
  3. Open Developer Tools (F12 or Cmd+Option+I)
  4. Go to the Network tab
  5. Navigate to any page on the Polarion server (e.g. refresh the page)
  6. Click on any request to the server
  7. In the Headers section, find the Cookie request header
  8. Copy the entire cookie value string (e.g. JSESSIONID=ABC123; X-CSRF-Token=DEF456; ...)

Then save it with svncli login:

svncli login --cookie "JSESSIONID=ABC123; X-CSRF-Token=DEF456" https://your-server.com

After this, all commands to that server will use the saved session automatically.

Tip: In Chrome, you can also right-click a request in the Network tab → Copy → Copy as cURL, then extract the cookie value from the -b or --cookie flag in the copied command.

How sync works

svncli tracks sync state in manifest files stored in ~/.svncli/manifests/. On each sync:

  1. First sync — compares by file size; uploads/downloads differences
  2. Subsequent syncs — uses SVN revision numbers + local file SHA-256 hashes:
    • Local file unchanged + remote revision unchanged → skip (fast, no hashing needed)
    • Local file changed → upload
    • Remote revision changed, local unchanged → skip (remote is newer)
    • New local file → upload
    • New remote file → download (in download direction)

The manifest enables efficient incremental syncs without downloading remote files to compare.

Corporate environments

For servers with self-signed or corporate CA certificates:

svncli --no-verify-ssl ls MyProject

Development

git clone https://github.com/pupca/svncli.git
cd svncli
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run unit tests (no server needed)
pytest tests/test_sync.py tests/test_client.py tests/test_models.py tests/test_util.py -v

# Run full suite including E2E (requires access to two Polarion servers)
export SVNCLI_SERVER_A="https://your-server.example.com"
export SVNCLI_ROOT_A="ProjectRoot"
export SVNCLI_SERVER_B="https://your-other-server.example.com"
export SVNCLI_ROOT_B="OtherProjectRoot"
pytest tests/ -v --cov=svncli --cov-report=html

# Run E2E with one server only (cross-server tests will be skipped)
export SVNCLI_SERVER_A="https://your-server.example.com"
export SVNCLI_ROOT_A="ProjectRoot"
pytest tests/ -v

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

svncli-1.0.0.tar.gz (40.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

svncli-1.0.0-py3-none-any.whl (27.3 kB view details)

Uploaded Python 3

File details

Details for the file svncli-1.0.0.tar.gz.

File metadata

  • Download URL: svncli-1.0.0.tar.gz
  • Upload date:
  • Size: 40.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for svncli-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d192388e37cb2e98318c09749d6a83fa901922e2ebf406a08df0eee909e03ed8
MD5 fbb435254761d6f500edfe5ca343fe6a
BLAKE2b-256 89532c4a920509f9d08cd2f4dd8d53444b79e85a9aa13bf1da0d50be5ec2a295

See more details on using hashes here.

Provenance

The following attestation bundles were made for svncli-1.0.0.tar.gz:

Publisher: publish.yml on pupca/svncli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file svncli-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: svncli-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 27.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for svncli-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c93475dfb56c99dd9d33c671d7fe45233cf8f92f0599748697c192e22189d242
MD5 1a05fef948e78a531d92808cf4b354ff
BLAKE2b-256 da640747caa227aef1495b307069def3910e52c89d036ef3834fda8ebcd8a9e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for svncli-1.0.0-py3-none-any.whl:

Publisher: publish.yml on pupca/svncli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page