This file is indexed.

/usr/share/pyshared/couchdb/tools/replicate.py is in python-couchdb 0.8-0ubuntu2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/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.
"""

from couchdb import http, client
import optparse
import sys
import time
import urllib
import urlparse
import fnmatch

def findpath(parser, s):
    '''returns (server url, path component)'''

    if s == '.':
        return client.DEFAULT_BASE_URL, ''
    if not s.startswith('http'):
        return client.DEFAULT_BASE_URL, s

    bits = urlparse.urlparse(s)
    res = http.Resource('%s://%s/' % (bits.scheme, bits.netloc), None)
    parts = bits.path.split('/')[1:]
    if parts and not parts[-1]:
        parts = parts[:-1]

    cut = None
    for i in range(0, len(parts) + 1):
        try:
            data = res.get_json(parts[:i])[2]
        except Exception:
            data = None
        if data and 'couchdb' in data:
            cut = i

    if cut is None:
        raise parser.error("'%s' does not appear to be a CouchDB" % s)

    base = res.url + (parts[:cut] and '/'.join(parts[:cut]) or '')
    return base, '/'.join(parts[cut:])

def main():

    usage = '%prog [options] <source> <target>'
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--continuous',
        action='store_true',
        dest='continuous',
        help='trigger continuous replication in cochdb')
    parser.add_option('--compact',
        action='store_true',
        dest='compact',
        help='compact target database after replication')

    options, args = parser.parse_args()
    if len(args) != 2:
        raise parser.error('need source and target arguments')

    # set up server objects

    src, tgt = args
    sbase, spath = findpath(parser, src)
    source = client.Server(sbase)
    tbase, tpath = findpath(parser, tgt)
    target = client.Server(tbase)

    # check database name specs

    if '*' in tpath:
        raise parser.error('invalid target path: must be single db or empty')
    elif '*' in spath and tpath:
        raise parser.error('target path must be empty with multiple sources')

    all = sorted(i for i in source if i[0] != '_') # Skip reserved names.
    if not spath:
        raise parser.error('source database must be specified')

    databases = [(i, i) for i in all if fnmatch.fnmatchcase(i, spath)]
    if not databases:
        raise parser.error("no source databases match glob '%s'" % spath)

    # do the actual replication

    for sdb, tdb in databases:

        start = time.time()
        print sdb, '->', tdb,
        sys.stdout.flush()

        if tdb not in target:
            target.create(tdb)
            print "created",
            sys.stdout.flush()

        sdb = '%s%s' % (sbase, urllib.quote(sdb, ''))
        if options.continuous:
            target.replicate(sdb, tdb, continuous=options.continuous)
        else:
            target.replicate(sdb, tdb)
        print '%.1fs' % (time.time() - start)
        sys.stdout.flush()

    if options.compact:
        for (sdb, tdb) in databases:
            print 'compact', tdb
            target[tdb].compact()

if __name__ == '__main__':
    main()