Skip to content

Instantly share code, notes, and snippets.

@kurohai
Forked from playpauseandstop/sync-it
Created August 4, 2020 14:43

Revisions

  1. @playpauseandstop playpauseandstop revised this gist Jan 15, 2011. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions sync-it
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    #!/usr/bin/env python
    #
    # Additional wrapper to ``rsync`` command with profiles.
    @@ -15,10 +14,10 @@
    # Installation
    # ============
    #
    # Place ``sync-it.py`` somewhere in your ``$PATH`` and give to it necessary
    # 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
    # Then, create config file with default options to rsync and profiles to sync
    # and store it on ``~/.config/sync-it/sync-it.conf``.
    #
    # Usage
  2. @playpauseandstop playpauseandstop created this gist Jan 15, 2011.
    157 changes: 157 additions & 0 deletions sync-it
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,157 @@

    #!/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.py`` somewhere in your ``$PATH`` and give to 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...')