133 lines
3.3 KiB
Python
Executable File
133 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import json
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
|
|
help_str = ('A config file `sync.json` has been created in {}. '
|
|
'Please specify the remote host and destination directory in this '
|
|
'config file and then run the sync script again.').format(os.path.join(os.getcwd(), '.config'))
|
|
config_filename = os.path.join('.config', 'sync.json')
|
|
rsync_path = os.getenv('RSYNC_PATH', default = 'rsync')
|
|
|
|
|
|
def in_source_tree():
|
|
return os.path.isfile('tools/sync.py')
|
|
|
|
|
|
def create_sample_config():
|
|
config_file = open(config_filename, mode='w')
|
|
data = {
|
|
'targets': {
|
|
'example': {
|
|
'host': 'Hostname',
|
|
'user': 'User to connect to the remote host as (optional)',
|
|
'path': 'Destination directory on remote host'
|
|
}
|
|
},
|
|
|
|
'default_target': 'example'
|
|
}
|
|
|
|
json.dump(data, config_file, indent=4)
|
|
|
|
|
|
def read_config():
|
|
config_file = None
|
|
try:
|
|
config_file = open('sync.json')
|
|
except (OSError, FileNotFoundError):
|
|
create_sample_config()
|
|
print(help_str)
|
|
exit(0)
|
|
|
|
return json.load(config_file)
|
|
|
|
|
|
def check_config(cfg):
|
|
if not 'targets' in cfg:
|
|
print('No targets specified in config file')
|
|
exit(-1)
|
|
|
|
|
|
def make_full_target(target):
|
|
path = target['path'].replace('\\', '/')
|
|
if path[-1] != '/':
|
|
path += '/'
|
|
|
|
out = '{}:{}'.format(target['host'], path)
|
|
|
|
if 'user' in target:
|
|
out = '{}@{}'.format(target['user'], out)
|
|
|
|
return out
|
|
|
|
|
|
def print_available_targets(targets):
|
|
print('Available targets:')
|
|
|
|
for name, target in targets.items():
|
|
print(' * {} ({})'.format(name, make_full_target(target)))
|
|
|
|
|
|
if not in_source_tree():
|
|
print('This script must be executed from the root of the Socks source tree')
|
|
exit(-1)
|
|
|
|
config = read_config()
|
|
check_config(config);
|
|
targets = config['targets']
|
|
|
|
if len(sys.argv) < 2:
|
|
print('No mode specified. Available modes:')
|
|
print(' * pull: Update the local source tree to match the remote source tree')
|
|
print(' * push: Upload the remote source tree to match the local source tree')
|
|
exit(0)
|
|
|
|
mode = sys.argv[1]
|
|
if mode != 'pull' and mode != 'push':
|
|
print('Invalid sync mode "{}"'.format(mode))
|
|
exit(-1)
|
|
|
|
target_name = ''
|
|
|
|
if len(sys.argv) < 3:
|
|
if 'default_target' in config:
|
|
target_name = config['default_target']
|
|
print('No target specified. Using default target "{}"'.format(target_name))
|
|
else:
|
|
print('No target specified (and no default target configured)')
|
|
print_available_targets(config['targets'])
|
|
exit(0)
|
|
|
|
if target_name not in targets:
|
|
print('Unknown target "{}"'.format(target_name))
|
|
print_available_targets(config['targets'])
|
|
exit(-1)
|
|
|
|
target = targets[target_name]
|
|
|
|
print('Syncing source tree with {} ({})'.format(make_full_target(target), mode))
|
|
rsync_args = [
|
|
rsync_path,
|
|
'-azhP',
|
|
'--exclude',
|
|
'build/'
|
|
]
|
|
|
|
if mode == 'pull':
|
|
rsync_args += [ make_full_target(target), '.' ]
|
|
else:
|
|
rsync_args += [ '.', make_full_target(target) ]
|
|
|
|
|
|
rsync = subprocess.Popen(rsync_args)
|
|
rsync.communicate()
|
|
|
|
if rsync.returncode == 0:
|
|
print('** Sync completed successfully')
|
|
else:
|
|
print('** Sync failed (error {})'.format(rsync.errorcode))
|
|
|
|
exit(rsync.returncode)
|