Skip to content

Commit

Permalink
Merge pull request #12 from zauberzeug/source-argument
Browse files Browse the repository at this point in the history
Make "source" a required positional argument (directory or workspace)
  • Loading branch information
rodja authored Oct 19, 2023
2 parents 1e3c1f9 + e9bb5fc commit 73146b8
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 40 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"--disable=C0111", // Missing docstring (in function/class/method)
"--disable=C0114", // Missing module docstring
"--disable=C0301", // Line too long (exceeds character limit)
"--disable=W0718" // Catching too general exception
"--disable=W0718", // Catching too general exception
"--disable=W1514" // Using open without explicitly specifying an encoding
],
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8",
Expand Down
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,39 @@ It works best if you have some kind of reload mechanism in place on the target (
## Usage

```bash
cd <my_project_folder>
livesync <username>@<host>
livesync <source> <username>@<host>
```

LiveSync uses rsync (SSH) to copy the files, so the `<username>@<host>` must be accessible via SSH (ideally by key, not password or passphrase, because it will be called over and over).

Press `CTRL-C` to abort the synchronization.

Positional arguments:

- `<source>`
local folder or VSCode workspace file
- `<username>@<host>`
target user and host (e.g. username@hostname)

Options:

- `--target-root TARGET_ROOT`
subfolder on target to synchronize to
- `--target-port TARGET_PORT`
SSH port on target
- `--on-change ON_CHANGE`
command to be executed on remote host after any file change
- `--mutex-interval MUTEX_INTERVAL`
interval in which mutex is updated

### Notes

- We suggest you have some auto-reloading in place on the (slow) target machine, like [NiceGUI](https://nicegui.io).
- Only one user per target host should run LiveSync at a time. Therefore LiveSync provides a mutex mechanism.
- By default `.git/` folders are not synchronized.
- All files and directories from the `.gitignore` of any source directory are also excluded from synchronization.
- You can create a `.syncignore` file in any source directory to skip additional files and directories from syncing.
- If LiveSync finds a VSCode workspace file, it will synchronize each directory listed in the `folders` section.

### Options

- `--on-change [command]` command to be executed on remote host after any file change
- `--source [SOURCE]` source folder on local host instead of VSCode workspace file
- `--mutex-interval [INTERVAL]` interval for updating the mutex
- `--target-port` to specify the SSH port
- `--target-root` to specify the root folder on the target machine
- If you pass a VSCode workspace file as `source`, LiveSync will synchronize each directory listed in the `folders` section.

## Installation

Expand Down
32 changes: 12 additions & 20 deletions livesync/livesync.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,29 @@ def git_summary(folders: List[Folder]) -> str:


async def async_main() -> None:
parser = argparse.ArgumentParser(description='Repeatedly synchronize local workspace with remote machine')
parser.add_argument('--on-change', type=str, help='command to be executed on remote host after any file change')
parser.add_argument('--source', type=str, help='source folder on local host instead of VSCode workspace file')
parser.add_argument('--mutex-interval', type=int, default=10, help='interval in which mutex is updated')
parser = argparse.ArgumentParser(description='Repeatedly synchronize local directories with remote machine')
parser.add_argument('source', type=str, help='local source folder or VSCode workspace file')
parser.add_argument('--target-root', type=str, default='', help='subfolder on target to synchronize to')
parser.add_argument('--target-port', type=int, default=22, help='SSH port on target')
parser.add_argument('--on-change', type=str, help='command to be executed on remote host after any file change')
parser.add_argument('--mutex-interval', type=int, default=10, help='interval in which mutex is updated')
parser.add_argument('host', type=str, help='the target host (e.g. username@hostname)')
args = parser.parse_args()
source = Path(args.source)
target = Target(host=args.host, port=args.target_port, root=Path(args.target_root))

folders: List[Folder] = []
workspaces = list(Path.cwd().glob('*.code-workspace'))
if args.source is None and workspaces:

if len(workspaces) > 1:
print('Multiple VSCode workspace files found.')
print('Provide --source argument or run livesync in a directory with a single *.code-workspace file.')
sys.exit(1)

print(f'Reading VSCode workspace file {workspaces[0]}...')

workspace = json.loads(workspaces[0].read_text())
if source.is_file():
workspace = json.loads(source.read_text())
paths = [Path(f['path']) for f in workspace['folders']]
folders = [Folder(p, target) for p in paths if p.is_dir()]
else:
source_path = Path(args.source or '.')
if not source_path.is_dir():
print(f'Invalid source path: {source_path}')
sys.exit(1)
folders = [Folder(source, target)]

folders = [Folder(source_path, target)]
for folder in folders:
if not folder.local_path.is_dir():
print(f'Invalid path: {folder.local_path}')
sys.exit(1)

print('Checking mutex...')
mutex = Mutex(target)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_existing_mutex_lets_sync_fail.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ cd /root/my_project
# fill mutex with some other user, so that livesync fails (`timeout` yields code 1, i.e. no timeout)
echo "some_user $(date -u +'%Y-%m-%dT%H:%M:%S.%6N')" > /target/.livesync_mutex
cat /target/.livesync_mutex
timeout 5 livesync --target-port 2222 --mutex-interval 1 target
timeout 5 livesync --target-port 2222 --mutex-interval 1 . target
assert_eq 1 $? "livesync should fail" || exit 1

# fill mutex with same user, so that livesync succeeds (`timeout` yields code 124, i.e. timeout)
echo "$HOSTNAME $(date -u +'%Y-%m-%dT%H:%M:%S.%6N')" > /target/.livesync_mutex
cat /target/.livesync_mutex
timeout 5 livesync --target-port 2222 --mutex-interval 1 target
timeout 5 livesync --target-port 2222 --mutex-interval 1 . target
assert_eq 124 $? "livesync should start" || exit 1
2 changes: 1 addition & 1 deletion tests/test_ignoring_mtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ touch /root/my_project/file.txt

# livesync should not overwrite the target file just because it is older
cd /root/my_project
livesync --target-port 2222 target &
livesync --target-port 2222 . target &
sleep 5
assert_gt $(stat -c %Y file.txt) $(stat -c %Y /target/my_project/file.txt) "mtime should be different"
2 changes: 1 addition & 1 deletion tests/test_non_existing_files_are_deleted.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ touch /target/my_project/file.txt

# livesync should delete the target file, because it is not present in source
cd /root/my_project
livesync --target-port 2222 target &
livesync --target-port 2222 . target &
sleep 5
assert_eq 0 "$(find /target -name '*.txt' | wc -l)" "target file should have been deleted"
2 changes: 1 addition & 1 deletion tests/test_on_change_command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ echo 'file content' > /root/my_project/file.txt

# livesync should create the target file and run the on-change command
cd /root/my_project
livesync --target-port 2222 --on-change "mktemp ../onchange-XXXXXXXX" target &
livesync --target-port 2222 --on-change "mktemp ../onchange-XXXXXXXX" . target &
sleep 5
assert_eq "file content" "$(cat /target/my_project/file.txt)" "wrong file content"
assert_eq 1 "$(find /target -name 'onchange-*' | wc -l)" "on-change should have been called once"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ echo '

# livesync should create the target files
cd /root/project1
livesync --target-port 2222 target &
livesync --target-port 2222 project1.code-workspace target &
sleep 5
assert_eq "file content 1" "$(cat /target/project1/file.txt)" "wrong file content"
assert_eq "file content 2" "$(cat /target/project2/file.txt)" "wrong file content"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_syncing_with_git_summary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ git add file.txt
git commit -m 'initial commit'

# livesync should create the target file
livesync --target-port 2222 --mutex-interval 1 target &
livesync --target-port 2222 --mutex-interval 1 . target &
sleep 5
assert_eq "file content" "$(cat /target/my_project/file.txt)" "wrong file content"

Expand Down
2 changes: 1 addition & 1 deletion tests/test_target_root.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ echo 'file content' > /root/my_project/file.txt

# livesync should create the target file and run the on-change command
cd /root/my_project
livesync --target-port 2222 --target-root foo/bar target &
livesync --target-port 2222 --target-root foo/bar . target &
sleep 5
assert_eq "file content" "$(cat /target/foo/bar/my_project/file.txt)" "wrong file content"

Expand Down

0 comments on commit 73146b8

Please sign in to comment.