Skip to content

Commit

Permalink
code review
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschindler committed Aug 31, 2022
1 parent d992dc6 commit 1a772a0
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 24 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build/
dist/
LiveSync.egg-info/
LiveSync.egg-info/
__pycache__
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Repeatedly synchronize local workspace with a (slow) remote machine.

## Use Case

[VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview) and similar tools are great as long as your remote machine is powerfull enough.
But if your target is a Raspberry Pi, Jetson Nano/Xavier/Orin, Beagle Board or similar it feels like coding in yelly.
Especcially if you run powerful extensions like Pylance.
[VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview) and similar tools are great as long as your remote machine is powerful enough.
But if your target is a Raspberry Pi, Jetson Nano/Xavier/Orin, Beagle Board or similar, it feels like coding in yelly.
Especially if you run powerful extensions like Pylance.
LiveSync solves this by watching your code and just copying the changed files to the slow remote machine.
It works best if you have some kind of relaoding meachism in place on the target.
It works best if you have some kind of reloading mechanism in place on the target.
We obviously recommend [NiceGUI](https://nicegui.io).

## Install
Expand All @@ -20,21 +20,21 @@ python3 -m pip install livesync
## Usage

```bash
cd <my_foder_with_vscode_workspace>
cd <my_folder_with_vscode_workspace>
livesync <username>@<host>
```

LiveSync uses rsync (ssh) to copy the files so the `<username>@<host>` must be accessable via ssh (ideally by key not password or passphrase, because it will be called over and over).
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 sync.
Press `CTRL-C` to abort the synchronization.

### Notes

- We suggest you have some auto-reloading in place on the (slow) target machine. Like [NiceGUI](https://nicegui.io).
- Only one user can run LiveSync at a time on a target host.
- By default `.git/` folders are not synced.
- All files and dirs from the `.gitignore` of any source directory are also excluded from sync.
- You can create a `.synignore` file in any source directory to skip additional files and dirs from syncing.
- 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 can run LiveSync at a time.
- 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.

## Development

Expand Down
17 changes: 9 additions & 8 deletions livesync/livesync.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from datetime import datetime
from glob import glob

from livesync import Mutex
from mutex import Mutex

processes: list[subprocess.Popen] = []

Expand All @@ -30,16 +30,17 @@ def sync(path: str, target_host: str) -> None:
if not os.path.isdir(path):
return
print(f'start syncing "{path}"')
excludes = ['.git/', '__pycache__/', '.DS_Store'] \
+ parse_ignore_file(f'{path}/.syncignore') + parse_ignore_file(f'{path}/.gitignore')
exclude_params = ' '.join([f'--exclude="{e}"' for e in excludes])
rsync = f'rsync --prune-empty-dirs --delete -avz --itemize-changes {exclude_params} {path}/ {target_host}:{os.path.basename(os.path.realpath(path))}'
excludes = ['.git/', '__pycache__/', '.DS_Store']
excludes += parse_ignore_file(f'{path}/.syncignore')
excludes += parse_ignore_file(f'{path}/.gitignore')
exclude_args = ' '.join([f'--exclude="{e}"' for e in excludes])
rsync_args = '--prune-empty-dirs --delete -avz --itemize-changes'
rsync = f'rsync {rsync_args} {exclude_args} {path}/ {target_host}:{os.path.basename(os.path.realpath(path))}'
start_process(rsync)
start_process(f'fswatch -r -l 0.1 -o {path} {exclude_params} | xargs -n1 -I{{}} {rsync}')
start_process(f'fswatch -r -l 0.1 -o {path} {exclude_args} | xargs -n1 -I{{}} {rsync}')


def main():

parser = argparse.ArgumentParser(description='Repeatedly synchronize local workspace with remote machine')
parser.add_argument('host', type=str, help='the target host (eg. username@hostname)')
args = parser.parse_args()
Expand All @@ -54,7 +55,7 @@ def main():
for p in workspace['folders']:
sync(p['path'], args.host)
while mutex.set():
for i in range(100):
for _ in range(100):
for p in processes:
# make stdout non-blocking (https://stackoverflow.com/a/59291466/364388)
os.set_blocking(p.stdout.fileno(), False)
Expand Down
8 changes: 5 additions & 3 deletions livesync/mutex.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import subprocess
import time

MUTEX_FILEPATH = '~/.livesync_mutex'


class Mutex:

Expand All @@ -14,7 +16,7 @@ def __init__(self, host: str) -> None:
def is_free(self) -> bool:
try:
output = subprocess.check_output(
['ssh', self.host, f'cat ~/.livesync_mutex || echo "{self.tag}"'],
['ssh', self.host, f'cat {MUTEX_FILEPATH} || echo "{self.tag}"'],
stderr=subprocess.DEVNULL).decode()
words = output.strip().split()
self.occupant = words[0]
Expand All @@ -30,7 +32,7 @@ def set(self) -> bool:
return False
try:
subprocess.check_output(
['ssh', self.host, f'echo "{self.tag}" > ~/.livesync_mutex'],
['ssh', self.host, f'echo "{self.tag}" > {MUTEX_FILEPATH}'],
stderr=subprocess.DEVNULL
)
return True
Expand All @@ -40,7 +42,7 @@ def set(self) -> bool:

def remove(self) -> None:
try:
subprocess.check_output(['ssh', self.host, f'rm ~/.livesync_mutex'], stderr=subprocess.DEVNULL)
subprocess.check_output(['ssh', self.host, f'rm {MUTEX_FILEPATH}'], stderr=subprocess.DEVNULL)
return True
except subprocess.CalledProcessError:
print('Could not remove mutex file')
Expand Down

0 comments on commit 1a772a0

Please sign in to comment.