xsyncfar
Project description
xsyncfar
Tool for one-directional sync across pre-mapped directory paths with find-and-replace rules applied to file content.
The sync direction is determined automatically by the directory you run the tool from — no flags needed.
Features
- Bidirectional mapping: run from either side of a mapping to sync in that direction
- Case-insensitive literal find-and-replace applied to file content during sync
- Only writes files whose content has actually changed (diff before write)
- Recursively processes all subdirectories
- Pre-flight summary with confirmation prompt before any changes are made
- Automatically creates missing destination directories and files
- Configurable file extension filter (with sensible defaults)
- Filename glob matching for extensionless files (e.g.
Dockerfile,Makefile,.env) - Git-style config discovery (walks up the directory tree)
- Works on Windows and Linux/macOS
- Python 3.6+, no dependencies beyond PyYAML
Installation
pip install xsyncfar
Or install from source:
git clone <repo-url>
cd xsyncfar
pip install -e .
Configuration
Create a .xsyncfar.yml file in your project root (or any parent directory). The tool will walk up the directory tree to find it.
syncmap:
# Path prefix prepended to all lab/prod paths in mappings
prefix: "/home/user/projects/"
# Optional: override the default file extensions to sync
# Defaults: .py .yml .yaml .json .txt .md
# extensions:
# - .yml
# - .tf
# - .py
# Optional: include files by filename glob pattern, regardless of extension.
# Use this for extensionless files like Dockerfile, Makefile, .env, etc.
# These files are treated as text files (replacements applied).
# match_file_globs:
# - "Dockerfile"
# - "Makefile"
# - ".env*"
# Optional: copy files with non-matching extensions as-is (binary copy, no replacements)
# Useful for images, binaries, shell scripts, etc.
# copy_other_files: true
# Optional: glob patterns for files/directories to exclude from sync entirely.
# Matched against both the item name and its path relative to the source root.
# .git is always ignored by default.
# ignore:
# - "*.pyc"
# - "__pycache__"
# - ".terraform"
# - "**/node_modules"
# Literal find-and-replace rules applied to file content (case-insensitive)
replacements:
- lab: "mylab" # string to find in source
prod: "mycompany" # string to replace with in destination
- lab: "dev-cluster"
prod: "prod-cluster"
# Directory path pairs (relative to prefix)
mappings:
- lab: "my-lab-project/helm-charts/my-chart"
prod: "my-prod-project/helm-charts/my-chart"
- lab: "my-lab-project/configs"
prod: "my-prod-project/configs"
How direction is determined
The tool compares your current working directory against all lab and prod paths in the config:
- If your CWD is inside a
labpath → syncs lab → prod (applyinglabpatterns, replacing withprodvalues) - If your CWD is inside a
prodpath → syncs prod → lab (reversing all replacements)
Usage
Navigate into any directory that matches a mapping (or a subdirectory of one), then run:
xsyncfar
# or
python -m xsyncfar
The tool will:
- Find the nearest
.xsyncfar.ymlwalking up from your CWD - Detect the sync direction from your CWD
- Show a pre-flight summary of what it will do
- Ask you to confirm before making any changes
- Sync all eligible files, applying find/replace rules
- Report all files that were written
Example session
============================================================
xsyncfar — pre-flight summary
============================================================
Direction : lab → prod
Source : /home/user/projects/my-lab-project/helm-charts/my-chart
Dest : /home/user/projects/my-prod-project/helm-charts/my-chart
Files : 8 eligible file(s) found
Replacements to apply:
'mylab' → 'mycompany'
'dev-cluster' → 'prod-cluster'
============================================================
Proceed with sync? [y/N]: y
Sync complete — 3 file(s) written:
values.yaml
templates/deployment.yaml
templates/configmap.yaml
Supported file extensions (default)
.py, .yml, .yaml, .json, .txt, .md
Override by adding an extensions list to your .xsyncfar.yml.
Matching extensionless files
Some important files (e.g. Dockerfile, Makefile, .env) have no extension. Use match_file_globs to include them as text files (replacements will be applied):
syncmap:
match_file_globs:
- "Dockerfile"
- "Makefile"
- ".env*"
Glob patterns are matched against the filename only (not the full path). Ignored files are still excluded even if they match a glob.
To also copy files with other extensions unchanged (binary copy, no replacements — useful for images, scripts, binaries), set copy_other_files: true in your syncmap.
Ignoring files and directories
Add an ignore list to your syncmap to exclude files or directories using glob patterns:
syncmap:
ignore:
- "*.pyc"
- "__pycache__"
- ".terraform"
- "**/node_modules"
- "dist"
Patterns are matched against both the item name (e.g. *.pyc matches any .pyc file) and the relative path from the source root (e.g. build/** excludes everything under build/). The .git directory is always ignored by default.
Running tests
python -m unittest discover -s tests -v
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xsyncfar-0.5.0.tar.gz.
File metadata
- Download URL: xsyncfar-0.5.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acf66871f12ab26c234b85d74c202a0dd02bf7641f8432f6b8492dccfc62ec2d
|
|
| MD5 |
b126b5458251ddb7d78d980307f51d5d
|
|
| BLAKE2b-256 |
ba1da416478ba9d48b349b58b0aece31cb0c7e212a0310065c7d7ef1e2cd1237
|
Provenance
The following attestation bundles were made for xsyncfar-0.5.0.tar.gz:
Publisher:
publish.yml on tkdpython/xsyncfar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xsyncfar-0.5.0.tar.gz -
Subject digest:
acf66871f12ab26c234b85d74c202a0dd02bf7641f8432f6b8492dccfc62ec2d - Sigstore transparency entry: 1348556885
- Sigstore integration time:
-
Permalink:
tkdpython/xsyncfar@04c2d2264b19b1d5ffa75e7b2858b4ed331745d5 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@04c2d2264b19b1d5ffa75e7b2858b4ed331745d5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file xsyncfar-0.5.0-py3-none-any.whl.
File metadata
- Download URL: xsyncfar-0.5.0-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93f282abd53382b61fce0e262fb92338b1d123696e614b2a46b75917f9d965c0
|
|
| MD5 |
5819b295ce1c1957e2d36f1e6dc27793
|
|
| BLAKE2b-256 |
85fea6c9d92a36df69c6c6da0a4282d596f2ce5825b1113648390b81a4dab492
|
Provenance
The following attestation bundles were made for xsyncfar-0.5.0-py3-none-any.whl:
Publisher:
publish.yml on tkdpython/xsyncfar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
xsyncfar-0.5.0-py3-none-any.whl -
Subject digest:
93f282abd53382b61fce0e262fb92338b1d123696e614b2a46b75917f9d965c0 - Sigstore transparency entry: 1348556949
- Sigstore integration time:
-
Permalink:
tkdpython/xsyncfar@04c2d2264b19b1d5ffa75e7b2858b4ed331745d5 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@04c2d2264b19b1d5ffa75e7b2858b4ed331745d5 -
Trigger Event:
release
-
Statement type: