Skip to content

Instantly share code, notes, and snippets.

@playpauseandstop
Created January 15, 2011 00:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save playpauseandstop/780578 to your computer and use it in GitHub Desktop.
Save playpauseandstop/780578 to your computer and use it in GitHub Desktop.
Additional wrapper to rsync command with profiles.
#!/usr/bin/env python
#
# Additional wrapper to ``rsync`` command with profiles.
#
# Requirements
# ============
#
# * Python_ 2.4 or higher
# * rsync_
#
# .. _Python: http://www.python.org/
# .. _rsync: http://rsync.samba.org/
#
# Installation
# ============
#
# Place ``sync-it`` somewhere in your ``$PATH`` and give it necessary
# permissions (``$ chmod +x``).
#
# Then, create config file with default options to rsync and profiles to sync
# and store it on ``~/.config/sync-it/sync-it.conf``.
#
# Usage
# =====
#
# $ sync-it [-i] [-o options] profile
#
# Example of configuration file
# =============================
#
# ::
#
# # You cannot use "rsync" as profile name. But, this block is not
# # required.
# [rsync]
# options = --progress -lzuogthvr --compress-level=9
#
# [profile]
# src = rsync://server/path/to/src/
# dest = /path/to/dest/
#
# [other_profile]
# options = -avz # You should redefine rsync options for each profile
# src = rsync://server/path/to/other_src/
# dest = ~/path/to/other_dest/ # You should use tilda in profile pathes
#
import os
import sys
from ConfigParser import ConfigParser, Error as ConfigParserError
from optparse import OptionParser
from subprocess import Popen
# Application settings
__usage__ = 'Usage: %prog [-i] [-o options] profile'
__version__ = '0.1-alpha'
# Necessary global vars
RSYNC = 'rsync'
def get_options():
"""
Build option parser, read profile from arguments passed to script then try
to read configuration for this profile and return configuration as
``dict`` instance.
"""
# Build option parser and parse arguments passed to script
parser = OptionParser(usage=__usage__, version=__version__)
parser.add_option('-i', '--invert', action='store_true', dest='invert',
default=False, help='Switch source and destination pathes for ' \
'selected profile.')
parser.add_option('-o', '--options', dest='options', default='',
help='Redefine global rsync options for selected profile.',
metavar='OPTIONS')
options, args = parser.parse_args()
if not len(args):
parser.error("You should pass 'profile' arg to the script.")
profile = args[0]
if profile == RSYNC:
parser.error('%r is reserved system name and you cannot use it as ' \
'profile name.' % RSYNC)
# Trying to read user configuration
filename = os.path.expanduser('~/.config/sync-it/sync-it.conf')
if not os.path.isfile(filename):
parser.error('Cannot read configuration from %r. Please, create ' \
'configuration file there first.' % filename)
config = ConfigParser()
try:
config.read(filename)
except ConfigParserError:
parser.error('Cannot parse configuration from %r. Please, check ' \
'syntax of your configuration file.' % filename)
if not profile in config.sections():
parser.error('Cannot find %r section in your configuration file.' % \
profile)
# User rsync options should used instead of profile rsync options
if options.options:
rsync_options = options.options
# Profile rsync options should used instead of global rsync options
if config.has_option(profile, 'options'):
rsync_options = config.get(profile, 'options')
elif config.has_option(RSYNC, 'options'):
rsync_options = config.get(RSYNC, 'options')
else:
rsync_options = ''
try:
dest = os.path.expanduser(config.get(profile, 'dest'))
src = os.path.expanduser(config.get(profile, 'src'))
except ConfigParserError, e:
parser.error(e)
return {'dest': options.invert and src or dest,
'options': rsync_options,
'profile': profile,
'src': options.invert and dest or src}
def main():
# Read script options
options = get_options()
# Execute rsync for selected profile
rsync(**options)
def rsync(profile, src, dest, options):
"""
Wrapper to executing rsync command.
"""
cmd = ' '.join((RSYNC, options, src, dest))
print('$ ' + cmd)
process = Popen(cmd, shell=True)
status = os.waitpid(process.pid, 0)[1]
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('OK OK! Exiting immediately...')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment