# HG changeset patch # User Jeff Hammel # Date 1389875379 28800 # Node ID 5c5edfb827b7f32510c0a356815de784b79e268e # Parent 54e9c335e239a60011c0f14bdb0c7da696e982d8 more the things diff -r 54e9c335e239 -r 5c5edfb827b7 setup.py --- a/setup.py Fri Jul 05 08:07:48 2013 -0700 +++ b/setup.py Thu Jan 16 04:29:39 2014 -0800 @@ -1,19 +1,19 @@ from setuptools import setup, find_packages -version = '0.2' +version = '0.2.1' setup(name='silvermirror', version=version, description="mirror files across hosts", long_description="""\ """, - classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[], keywords='mirror unison', author='Jeff Hammel', author_email='k0scist@gmail.com', url='http://explosivedecompression.net', license='GPL', - packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), + packages=['silvermirror'], include_package_data=True, zip_safe=False, install_requires=[ diff -r 54e9c335e239 -r 5c5edfb827b7 silvermirror/config.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/silvermirror/config.py Thu Jan 16 04:29:39 2014 -0800 @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +import optparse +import os +import sys + +from .utils import home +from martini.config import ConfigMunger + +class SilvermirrorConfiguration(object): + """ + SilverMirror configuration class + + The current form is an .ini file + [TODO: use `install_requires='configuration'`]: + + [::SilverMirror::] + ... + """ + + main_section = '::SilverMirror::' + + def __init__(self, filename=None): + if filename is not None: + self.read_config(filename) + def read_config(self, filename): + + # read file + config = ConfigMunger(filename).dict() + + # main configuration + main = config.pop(, {}) + main.setdefault('basedir', home()) + main['ignore'] = main.get('ignore', '').split() # patterns to ignore - + main['hosts'] = main.get('hosts', '').split() + main['timeout'] = float(main.get('timeout', '10.')) + + # password prompt + truth = dict([(str(i).lower(), i) for i in (True, False)]) + password = main.get('password', 'true') + try: + main['password'] = truth[password.lower()] + except KeyError: + raise KeyError("password must be True or False (You gave: '%s')" % password) + + # resources + for resource in config: + + # directory of resource + directory = config[resource].get('directory', resource) + if os.path.isabs(directory): + raise NotImplementedError("absolute directories will not work for now so....don't do this!") + + else: + directory = os.path.join(main['basedir'], directory) + config[resource]['directory'] = directory.rstrip(os.path.sep) + + # per-resource files to ignore + # XXX regexps for now (see `man unison`) + # - this is bad as whitespace patterns cannot be ignored + config[resource]['ignore'] = main['ignore'][:] + config[resource].get('ignore', '').split() + + # set + return ditionary of config + self.main = main + self.resources = config + config = (main, config) + +def main(args=sys.argv[1:]): + + usage = '%prog [options]' + parser = optparse.OptionParser(usage=usage, description=__doc__) + options, args = parser.parse_args(args) + +if __name__ == '__main__': + main() diff -r 54e9c335e239 -r 5c5edfb827b7 silvermirror/unify.py --- a/silvermirror/unify.py Fri Jul 05 08:07:48 2013 -0700 +++ b/silvermirror/unify.py Thu Jan 16 04:29:39 2014 -0800 @@ -17,6 +17,7 @@ # XXX needed? raise NotImplementedError('Need to specify a config file, like\n~/silvermirror/silvermirror.ini') + def read_config(filename): config = ConfigMunger(filename).dict() @@ -59,15 +60,18 @@ config = { 'main': main, 'resources': config } return config -def unify(conf, _resources, test=False): +def unify(conf, _resources, test=False, verbose=True, notification_prefix='\n*** SilverMirror; '): + # TODO: -> OO + + # log function + def log(message): + if verbose: + print ("%s%s" % (notification_prefix, message)) # passwords pw = {} - # XXX needed for now - assert conf['main']['basedir'] == home() - - ### determine hosts to sync with + # determine hosts to sync with hosts = conf['hosts'] addresses = ip_addresses().values() hosts = hosts.difference(addresses) # don't sync with self @@ -84,11 +88,9 @@ continue _hosts.append(host) hosts = _hosts - if test: - print 'Hosts:' - for host in hosts: - print host - assert hosts + log("Hosts:\n%s" % '\n'.join(hosts)) + if not hosts: + raise AssertionError("No hosts specified") if conf['main']['password']: for host in hosts: @@ -110,7 +112,7 @@ resources = { key: value } break if test: - print 'Resources:' + log("Resources:\n%s") pprint(resources) ### choose reflector backend @@ -119,7 +121,12 @@ ### sync with hosts os.chdir(conf['main']['basedir']) - for resource in resources: + for index, resource in enumerate(resources): + + # echo resource + log("syncing:'%s' [%d/%d]" % (resource, index, len(resources))) + + # loop over hosts for host in hosts: reflector.sync(host, resource, resources[resource]['ignore'], pw.get('host'), test) os.chdir(cwd) @@ -151,13 +158,11 @@ else: conf = make_config(user_conf) - # XXX needed for now - assert conf['main']['basedir'] == home() - # fix up configuration from command line options conf['hosts'] = set(options.hosts or conf['main']['hosts']) conf['main']['password'] = options.password and conf['main']['password'] + # mirror all the things unify(conf, args, options.test) if __name__ == '__main__':