#!/usr/bin/python # # skel -- keep your basic configuration files in sync on remote machines # # installation instructions: # 1. download yamlconfig.py from # http://trevor.caira.com/scripts/yamlconfig.py and put it on your # python path in a package called trevor. # 2. create a configuration file ~/.config/skel/config.yml containing # ``files:`` and ``pull from:`` entries. an example config.yml is # available at http://trevor.caira.com/scripts/config.yml. # 3. copy skel to your path and make it executable import os, sys from trevor.yamlconfig import ConfigurationError, YamlConfig DEFAULTS = {'config': os.path.expanduser('~/.config/skel/config.yml'), 'output': 'skel.tar.gz'} _commands = {} commands = _commands.get def command(func): globals()['_commands'][func.func_code.co_name] = func return func def ext2taropt(filename): if filename.endswith('.bz2'): return 'j' elif filename.endswith('.gz'): return 'z' return '' def parse_options(): from optparse import OptionParser parser = OptionParser(usage='''usage: %%prog [OPTIONS] [FILE] COMMAND where COMMAND is one of: %s''' % '\n '.join(_commands.keys())) parser.add_option('-c', '--config', dest='config', default=None, help='Specify an alternate configuration file \ (default: %r).' % DEFAULTS['config']) parser.add_option('-o', '--output', dest='output', default=None, help='Specify an alternate output file (default: \ %r).' % DEFAULTS['output']) options, args = parser.parse_args() if options.config is None: options.config = DEFAULTS['config'] return options, args class UpdateSkelConfig(YamlConfig): def __init__(self, options, args): super(UpdateSkelConfig, self).__init__(options, args) if 'output' not in self: if options.output is None: self['output'] = DEFAULTS['output'] else: self['output'] = options.output if len(args) != 1: raise ConfigurationError('command must be specified') self['command'] = args[0] @command def bundle(config): from subprocess import call compress = ext2taropt(config['output']) rv = call(['tar', 'cf%s' % compress, config['output']] + ['--no-recursion', '-C', os.path.expanduser('~')] + config['files']) if rv != 0: sys.stderr.write('tar exited with error code %d\n' % rv) @command def pull(config): from subprocess import Popen, PIPE from urllib2 import urlopen u = urlopen(config['pull from']) compress = ext2taropt(config['pull from']) tar = Popen(['tar', 'xf%s' % compress, '-', '-C', os.path.expanduser('~')], stdin=PIPE) try: tar.stdin.write(u.read()) finally: tar.stdin.close() rv = tar.wait() if rv != 0: sys.stderr.write('tar exited with error code %d\n' % rv) def main(): config = UpdateSkelConfig(*parse_options()) globals()[config['command']](config) if __name__ == '__main__': main()