#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2009 Maximillian Dornseif <md@hudora.de>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.

"""
This script replicates databases from one CouchDB server to an other.

This is mainly for backup purposes or "priming" a new server before
setting up trigger based replication. But you can also use the
'--continuous' option to set up automatic replication on newer
CouchDB versions.

Use 'python replicate.py --help' to get more detailed usage
instructions.

Be careful when using 127.0.0.1 as the source-server or target-server.
With pull replication you can use 127.0.0.1 on the target-server.
With push replication you can use 127.0.0.1 on the source-server.
But I suggest you always use Fully Qualified domain names.
"""

import couchdb.client
import optparse
import sys
import time

def compact(server, dbnames):
    for dbname in dbnames:
        sys.stdout.flush()
        db = server[dbname]
        db.resource.post('_compact')

def main():
    usage = '%prog [options]'
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--source-server',
        action='store',
        dest='source_url',
        help='the url of the server to replicate from')
    parser.add_option('--target-server',
        action='store',
        dest='target_url',
        default="http://127.0.0.1:5984",
        help='the url of the server to replicate to [%default]')
    parser.add_option('--database',
        action='append',
        dest='dbnames',
        help='Database to replicate. Can be given more than once. [all databases]')
    parser.add_option('--no-target-compaction',
        action='store_false',
        dest='compact_target',
        help='do not start compaction of target after replications')
    parser.add_option('--continuous',
        action='store_true',
        dest='continuous',
        help='trigger continuous replication in cochdb')
    parser.add_option('--push',
        action='store_true',
        help='use push instead of pull replication')

    options, args = parser.parse_args()

    if not options.target_url or (not options.source_url):
        parser.error("Need at least --source-server and --target-server")
        sys.exit(1)

    if not options.source_url.endswith('/'):
        options.source_url = options.source_url + '/'
    if not options.target_url.endswith('/'):
        options.target_url = options.target_url + '/'
    source_server = couchdb.client.Server(options.source_url)
    target_server = couchdb.client.Server(options.target_url)

    if not options.dbnames:
        dbnames = sorted(i for i in source_server)
    else:
        dbnames = options.dbnames

    targetdbs = sorted(i for i in target_server)
    for dbname in sorted(dbnames, reverse=True):
        start = time.time()
        print dbname,
        sys.stdout.flush()
        if dbname not in targetdbs:
            target_server.create(dbname)
            print "created",
            sys.stdout.flush()
        body = {}
        if options.continuous:
            body['continuous'] = True
        if options.push:
            body.update({'source': dbname, 'target': '%s%s' % (options.target_url, dbname)})
            source_server.resource.post('_replicate', body)
        else:
            # pull seems to be more reliable than push
            body.update({'source': '%s%s' % (options.source_url, dbname), 'target': dbname})
            target_server.resource.post('_replicate', body)
        print "%.1f s" % (time.time() - start)
    
    if options.compact_target:
        compact(target_server, dbnames)

if __name__ == '__main__':
    main()

@@ -1076,16 +1076,17 @@
 main():%0A
+%0A
     usag
@@ -2503,24 +2503,25 @@
 t_url + '/'%0A
+%0A
     source_s
@@ -2855,16 +2855,17 @@
 =True):%0A
+%0A
         
@@ -3062,32 +3062,33 @@
 .stdout.flush()%0A
+%0A
         body = %7B
@@ -3158,16 +3158,17 @@
  = True%0A
+%0A
         
@@ -3551,32 +3551,33 @@
 plicate', body)%0A
+%0A
         print %22%25
@@ -3578,16 +3578,15 @@
 int 
-%22
+'
 %25.1f
- s%22
+s'
  %25 (

Improve formatting in replication script.