tsync 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tsync-0.1.0/.gitignore ADDED
@@ -0,0 +1,47 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ venv/
26
+ ENV/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Testing
35
+ .pytest_cache/
36
+ .coverage
37
+ htmlcov/
38
+
39
+ # Distribution
40
+ *.tar.gz
41
+ *.whl
42
+
43
+ # Claude Code
44
+ .claude/
45
+
46
+ # Local notes
47
+ TODO.md
tsync-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 jayghoshter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
tsync-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: tsync
3
+ Version: 0.1.0
4
+ Summary: rsync wrapper to sync files between local machine and remotes with push/pull workflow
5
+ Project-URL: Homepage, https://github.com/jayghoshter/tsync
6
+ Project-URL: Repository, https://github.com/jayghoshter/tsync
7
+ Author: jayghoshter
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: backup,remote,rsync,sync
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: System :: Archiving :: Mirroring
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: deepdiff>=6.0
26
+ Requires-Dist: python-magic>=0.4
27
+ Requires-Dist: rich>=13.0
28
+ Requires-Dist: ruamel-yaml>=0.18
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
31
+ Requires-Dist: pytest>=7.0; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # tsync
35
+
36
+ An rsync wrapper for syncing entire or partial directory trees between machines
37
+ with a simple push/pull workflow.
38
+
39
+ > [!TIP]
40
+ > `tsync` can be invoked from any nested subdirectory to synchronize the entire tree.
41
+
42
+ > [!CAUTION]
43
+ > This tool is tested for the authors workflow and has worked flawlessly for the
44
+ > past several years. However, some caution is advised as this tool deals with
45
+ > synchronizing files across devices. Please keep backups.
46
+
47
+ > [!NOTE]
48
+ > Feel free to request features or open bug tickets.
49
+
50
+ ## Features
51
+
52
+ - **Push/Pull workflow**: Sync files to multiple remotes or pull from a single source
53
+ - **Config-based remotes**: Define remotes once in `.tsync.yaml`, use by name
54
+ - **Directory structure preservation**: Maintains relative paths from the config root
55
+ - **Flexible excludes/includes**: Configure patterns in YAML or override via CLI
56
+ - **Diff with remotes**: Compare local and remote states before syncing
57
+ - **Remote command execution**: Run commands on remotes in the corresponding directory
58
+
59
+ ### Author's use case
60
+ - Have a root directory filled with subdirectories for different simulations
61
+ - Need to run simulations distributed across different machines
62
+ - With the configs set up locally,
63
+ - `tsync push server-1 -f dir01`, `tsync push server-2 -f dir02`, ...
64
+ - or from `dir01`, `tsync push server-1 -f .`
65
+ - Run simulations on servers. It is now possible to use `tsync cmd ...` for remote execution
66
+ - Run post processing on servers. `tsync cmd ...`
67
+ - Only pull post-processed data to verify, `tsync pull server-1 -f dir01/post`, ...
68
+
69
+ You may also set each simulation directory as a root with only one specific remote where it is to be executed.
70
+
71
+ ## Installation
72
+
73
+ ```bash
74
+ pip install tsync
75
+ ```
76
+
77
+ Or with [uv](https://docs.astral.sh/uv/):
78
+
79
+ ```bash
80
+ uv tool install tsync # install globally as a CLI tool
81
+ uvx tsync # run without installing
82
+ ```
83
+
84
+ Or install from source:
85
+
86
+ ```bash
87
+ git clone https://github.com/jayghoshter/tsync.git
88
+ cd tsync
89
+ pip install -e .
90
+ ```
91
+
92
+ ## Quick Start
93
+
94
+ 1. Create a `.tsync.yaml` in your project root:
95
+
96
+ ```yaml
97
+ remotes:
98
+ server: user@hostname:/path/to/backup
99
+ nas: nas:/volume1/projects # if 'nas' is in ssh config
100
+ local_backup: /mnt/backup/projects
101
+
102
+ excludes:
103
+ - __pycache__
104
+ - .git
105
+ - "*.pyc"
106
+ - node_modules
107
+
108
+ includes:
109
+ - important.pyc # override excludes for specific files
110
+ ```
111
+
112
+ 2. Push to a remote:
113
+
114
+ ```bash
115
+ cd /path/to/project/subdir
116
+ tsync push server
117
+ ```
118
+
119
+ This syncs the current directory to `user@hostname:/path/to/backup/subdir/`.
120
+
121
+ 3. Pull from a remote:
122
+
123
+ ```bash
124
+ tsync pull server
125
+ ```
126
+
127
+ ## Usage
128
+
129
+ ### Push
130
+
131
+ Push current directory to one or more remotes:
132
+
133
+ ```bash
134
+ tsync push server # push to 'server'
135
+ tsync push server nas # push to multiple remotes
136
+ tsync push all # push to all configured remotes
137
+ tsync push server -f file.txt # push specific files only
138
+ ```
139
+
140
+ ### Pull
141
+
142
+ Pull from a remote to current directory:
143
+
144
+ ```bash
145
+ tsync pull server
146
+ tsync pull server -f file.txt # pull specific files only
147
+ ```
148
+
149
+ ### Diff
150
+
151
+ Compare local and remote states:
152
+
153
+ ```bash
154
+ tsync diff server # quick rsync-based diff
155
+ tsync diff server --copy # detailed diff with file contents
156
+ ```
157
+
158
+ ### Remote Commands
159
+
160
+ Run commands on remotes in the corresponding directory:
161
+
162
+ ```bash
163
+ tsync cmd --target server -- ls -la
164
+ tsync cmd --target server -- git status
165
+ ```
166
+
167
+ ### Edit Config
168
+
169
+ Open the nearest `.tsync.yaml` in your editor:
170
+
171
+ ```bash
172
+ tsync edit
173
+ ```
174
+
175
+ ## Options
176
+
177
+ | Option | Description |
178
+ |--------|-------------|
179
+ | `-y, --no-confirm` | Don't prompt before syncing |
180
+ | `-d, --dry-run` | Show what would be synced without doing it |
181
+ | `-m, --mkdir` | Create remote directories before syncing |
182
+ | `--delete` | Delete extraneous files on receiver |
183
+ | `--delete-excluded` | Also delete excluded files on receiver |
184
+ | `-ne, --no-excludes` | Ignore all exclude patterns |
185
+ | `-e, --excludes` | Additional exclude patterns |
186
+ | `-i, --includes` | Additional include patterns |
187
+ | `-f, --files` | Specific files/directories to sync |
188
+
189
+ Additional rsync options can be passed directly:
190
+
191
+ ```bash
192
+ tsync push server -- --compress-level=9
193
+ ```
194
+
195
+ ## Configuration
196
+
197
+ The `.tsync.yaml` file is searched upward from the current directory. The directory containing the config file is considered the "root" - all relative paths are computed from there.
198
+
199
+ ```yaml
200
+ remotes:
201
+ # SSH remotes (rsync over SSH)
202
+ server: user@host:/path/to/root
203
+ shortname: hostname:/path/to/root # uses ssh config
204
+
205
+ # Local paths
206
+ backup: /mnt/external/backup
207
+
208
+ excludes:
209
+ - __pycache__
210
+ - "*.pyc"
211
+ - .git
212
+ - .env
213
+ - node_modules
214
+
215
+ includes:
216
+ - .env.example # include despite .env exclude pattern
217
+ ```
218
+
219
+ ## How It Works
220
+
221
+ 1. Searches upward for `.tsync.yaml` to find the project root
222
+ 2. Computes the relative path from root to current directory
223
+ 3. Constructs the remote path: `<remote_root>/<relative_path>/`
224
+ 4. Runs rsync with the configured options
225
+
226
+ This means if you're in `/home/user/projects/myapp/src/` and the `.tsync.yaml` is in `/home/user/projects/myapp/`, syncing to `server: host:/backup` will target `host:/backup/src/`.
227
+
228
+ ## Requirements
229
+
230
+ - Python 3.10+
231
+ - rsync (installed on both local and remote machines)
232
+ - SSH access to remote machines (for SSH remotes)
233
+
234
+ ## License
235
+
236
+ MIT
tsync-0.1.0/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # tsync
2
+
3
+ An rsync wrapper for syncing entire or partial directory trees between machines
4
+ with a simple push/pull workflow.
5
+
6
+ > [!TIP]
7
+ > `tsync` can be invoked from any nested subdirectory to synchronize the entire tree.
8
+
9
+ > [!CAUTION]
10
+ > This tool is tested for the authors workflow and has worked flawlessly for the
11
+ > past several years. However, some caution is advised as this tool deals with
12
+ > synchronizing files across devices. Please keep backups.
13
+
14
+ > [!NOTE]
15
+ > Feel free to request features or open bug tickets.
16
+
17
+ ## Features
18
+
19
+ - **Push/Pull workflow**: Sync files to multiple remotes or pull from a single source
20
+ - **Config-based remotes**: Define remotes once in `.tsync.yaml`, use by name
21
+ - **Directory structure preservation**: Maintains relative paths from the config root
22
+ - **Flexible excludes/includes**: Configure patterns in YAML or override via CLI
23
+ - **Diff with remotes**: Compare local and remote states before syncing
24
+ - **Remote command execution**: Run commands on remotes in the corresponding directory
25
+
26
+ ### Author's use case
27
+ - Have a root directory filled with subdirectories for different simulations
28
+ - Need to run simulations distributed across different machines
29
+ - With the configs set up locally,
30
+ - `tsync push server-1 -f dir01`, `tsync push server-2 -f dir02`, ...
31
+ - or from `dir01`, `tsync push server-1 -f .`
32
+ - Run simulations on servers. It is now possible to use `tsync cmd ...` for remote execution
33
+ - Run post processing on servers. `tsync cmd ...`
34
+ - Only pull post-processed data to verify, `tsync pull server-1 -f dir01/post`, ...
35
+
36
+ You may also set each simulation directory as a root with only one specific remote where it is to be executed.
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install tsync
42
+ ```
43
+
44
+ Or with [uv](https://docs.astral.sh/uv/):
45
+
46
+ ```bash
47
+ uv tool install tsync # install globally as a CLI tool
48
+ uvx tsync # run without installing
49
+ ```
50
+
51
+ Or install from source:
52
+
53
+ ```bash
54
+ git clone https://github.com/jayghoshter/tsync.git
55
+ cd tsync
56
+ pip install -e .
57
+ ```
58
+
59
+ ## Quick Start
60
+
61
+ 1. Create a `.tsync.yaml` in your project root:
62
+
63
+ ```yaml
64
+ remotes:
65
+ server: user@hostname:/path/to/backup
66
+ nas: nas:/volume1/projects # if 'nas' is in ssh config
67
+ local_backup: /mnt/backup/projects
68
+
69
+ excludes:
70
+ - __pycache__
71
+ - .git
72
+ - "*.pyc"
73
+ - node_modules
74
+
75
+ includes:
76
+ - important.pyc # override excludes for specific files
77
+ ```
78
+
79
+ 2. Push to a remote:
80
+
81
+ ```bash
82
+ cd /path/to/project/subdir
83
+ tsync push server
84
+ ```
85
+
86
+ This syncs the current directory to `user@hostname:/path/to/backup/subdir/`.
87
+
88
+ 3. Pull from a remote:
89
+
90
+ ```bash
91
+ tsync pull server
92
+ ```
93
+
94
+ ## Usage
95
+
96
+ ### Push
97
+
98
+ Push current directory to one or more remotes:
99
+
100
+ ```bash
101
+ tsync push server # push to 'server'
102
+ tsync push server nas # push to multiple remotes
103
+ tsync push all # push to all configured remotes
104
+ tsync push server -f file.txt # push specific files only
105
+ ```
106
+
107
+ ### Pull
108
+
109
+ Pull from a remote to current directory:
110
+
111
+ ```bash
112
+ tsync pull server
113
+ tsync pull server -f file.txt # pull specific files only
114
+ ```
115
+
116
+ ### Diff
117
+
118
+ Compare local and remote states:
119
+
120
+ ```bash
121
+ tsync diff server # quick rsync-based diff
122
+ tsync diff server --copy # detailed diff with file contents
123
+ ```
124
+
125
+ ### Remote Commands
126
+
127
+ Run commands on remotes in the corresponding directory:
128
+
129
+ ```bash
130
+ tsync cmd --target server -- ls -la
131
+ tsync cmd --target server -- git status
132
+ ```
133
+
134
+ ### Edit Config
135
+
136
+ Open the nearest `.tsync.yaml` in your editor:
137
+
138
+ ```bash
139
+ tsync edit
140
+ ```
141
+
142
+ ## Options
143
+
144
+ | Option | Description |
145
+ |--------|-------------|
146
+ | `-y, --no-confirm` | Don't prompt before syncing |
147
+ | `-d, --dry-run` | Show what would be synced without doing it |
148
+ | `-m, --mkdir` | Create remote directories before syncing |
149
+ | `--delete` | Delete extraneous files on receiver |
150
+ | `--delete-excluded` | Also delete excluded files on receiver |
151
+ | `-ne, --no-excludes` | Ignore all exclude patterns |
152
+ | `-e, --excludes` | Additional exclude patterns |
153
+ | `-i, --includes` | Additional include patterns |
154
+ | `-f, --files` | Specific files/directories to sync |
155
+
156
+ Additional rsync options can be passed directly:
157
+
158
+ ```bash
159
+ tsync push server -- --compress-level=9
160
+ ```
161
+
162
+ ## Configuration
163
+
164
+ The `.tsync.yaml` file is searched upward from the current directory. The directory containing the config file is considered the "root" - all relative paths are computed from there.
165
+
166
+ ```yaml
167
+ remotes:
168
+ # SSH remotes (rsync over SSH)
169
+ server: user@host:/path/to/root
170
+ shortname: hostname:/path/to/root # uses ssh config
171
+
172
+ # Local paths
173
+ backup: /mnt/external/backup
174
+
175
+ excludes:
176
+ - __pycache__
177
+ - "*.pyc"
178
+ - .git
179
+ - .env
180
+ - node_modules
181
+
182
+ includes:
183
+ - .env.example # include despite .env exclude pattern
184
+ ```
185
+
186
+ ## How It Works
187
+
188
+ 1. Searches upward for `.tsync.yaml` to find the project root
189
+ 2. Computes the relative path from root to current directory
190
+ 3. Constructs the remote path: `<remote_root>/<relative_path>/`
191
+ 4. Runs rsync with the configured options
192
+
193
+ This means if you're in `/home/user/projects/myapp/src/` and the `.tsync.yaml` is in `/home/user/projects/myapp/`, syncing to `server: host:/backup` will target `host:/backup/src/`.
194
+
195
+ ## Requirements
196
+
197
+ - Python 3.10+
198
+ - rsync (installed on both local and remote machines)
199
+ - SSH access to remote machines (for SSH remotes)
200
+
201
+ ## License
202
+
203
+ MIT
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "tsync"
7
+ version = "0.1.0"
8
+ description = "rsync wrapper to sync files between local machine and remotes with push/pull workflow"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "jayghoshter" }
14
+ ]
15
+ keywords = ["rsync", "sync", "backup", "remote"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: System Administrators",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: POSIX :: Linux",
23
+ "Operating System :: MacOS",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Topic :: System :: Archiving :: Mirroring",
29
+ "Topic :: Utilities",
30
+ ]
31
+
32
+ dependencies = [
33
+ "rich>=13.0",
34
+ "ruamel.yaml>=0.18",
35
+ "deepdiff>=6.0",
36
+ "python-magic>=0.4",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "pytest>=7.0",
42
+ "pytest-cov>=4.0",
43
+ ]
44
+
45
+ [project.scripts]
46
+ tsync = "tsync.cli:main"
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/jayghoshter/tsync"
50
+ Repository = "https://github.com/jayghoshter/tsync"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/tsync"]
54
+
55
+ [tool.pytest.ini_options]
56
+ testpaths = ["tests"]
57
+ python_files = ["test_*.py"]
58
+ markers = [
59
+ "integration: tests that require rsync and filesystem operations",
60
+ ]
@@ -0,0 +1,3 @@
1
+ """tsync: rsync wrapper for syncing files with push/pull workflow."""
2
+
3
+ __version__ = "0.1.0"