contrib/shrink-revlog.py
author Matt Mackall <mpm@selenic.com>
Sun, 11 Oct 2009 13:58:53 -0500
changeset 9580 25858f9e65e8
parent 9515 f7d85980261c
child 9712 18b134ef294c
permissions -rwxr-xr-x
run-tests: add --noskips option
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9515
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     1
#!/usr/bin/env python
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     2
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     3
"""\
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     4
Reorder a revlog (by default the the manifest file in the current
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     5
repository) to save space.  Specifically, this topologically sorts the
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     6
revisions in the revlog so that revisions on the same branch are adjacent
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     7
as much as possible.  This is a workaround for the fact that Mercurial
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     8
computes deltas relative to the previous revision rather than relative to a
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
     9
parent revision.  This is *not* safe to run on a changelog.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    10
"""
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    11
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    12
# Originally written by Benoit Boissinot <benoit.boissinot at ens-lyon.org>
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    13
# as a patch to rewrite-log.  Cleaned up, refactored, documented, and
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    14
# renamed by Greg Ward <greg at gerg.ca>.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    15
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    16
# XXX would be nice to have a way to verify the repository after shrinking,
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    17
# e.g. by comparing "before" and "after" states of random changesets
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    18
# (maybe: export before, shrink, export after, diff).
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    19
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    20
import sys, os, tempfile
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    21
import optparse
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    22
from mercurial import ui as ui_, hg, revlog, transaction, node, util
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    23
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    24
def toposort(rl):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    25
    write = sys.stdout.write
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    26
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    27
    children = {}
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    28
    root = []
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    29
    # build children and roots
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    30
    write('reading %d revs ' % len(rl))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    31
    try:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    32
        for i in rl:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    33
            children[i] = []
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    34
            parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    35
            # in case of duplicate parents
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    36
            if len(parents) == 2 and parents[0] == parents[1]:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    37
                del parents[1]
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    38
            for p in parents:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    39
                assert p in children
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    40
                children[p].append(i)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    41
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    42
            if len(parents) == 0:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    43
                root.append(i)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    44
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    45
            if i % 1000 == 0:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    46
                write('.')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    47
    finally:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    48
        write('\n')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    49
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    50
    # XXX this is a reimplementation of the 'branchsort' topo sort
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    51
    # algorithm in hgext.convert.convcmd... would be nice not to duplicate
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    52
    # the algorithm
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    53
    write('sorting ...')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    54
    visit = root
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    55
    ret = []
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    56
    while visit:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    57
        i = visit.pop(0)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    58
        ret.append(i)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    59
        if i not in children:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    60
            # This only happens if some node's p1 == p2, which can
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    61
            # happen in the manifest in certain circumstances.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    62
            continue
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    63
        next = []
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    64
        for c in children.pop(i):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    65
            parents_unseen = [p for p in rl.parentrevs(c)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    66
                              if p != node.nullrev and p in children]
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    67
            if len(parents_unseen) == 0:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    68
                next.append(c)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    69
        visit = next + visit
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    70
    write('\n')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    71
    return ret
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    72
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    73
def writerevs(r1, r2, order, tr):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    74
    write = sys.stdout.write
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    75
    write('writing %d revs ' % len(order))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    76
    try:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    77
        count = 0
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    78
        for rev in order:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    79
            n = r1.node(rev)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    80
            p1, p2 = r1.parents(n)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    81
            l = r1.linkrev(rev)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    82
            t = r1.revision(n)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    83
            n2 = r2.addrevision(t, tr, l, p1, p2)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    84
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    85
            if count % 1000 == 0:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    86
                write('.')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    87
            count += 1
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    88
    finally:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    89
        write('\n')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    90
    
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    91
def report(olddatafn, newdatafn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    92
    oldsize = float(os.stat(olddatafn).st_size)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    93
    newsize = float(os.stat(newdatafn).st_size)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    94
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    95
    # argh: have to pass an int to %d, because a float >= 2^32 
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    96
    # blows up under Python 2.5 or earlier
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    97
    sys.stdout.write('old file size: %12d bytes (%6.1f MiB)\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    98
                     % (int(oldsize), oldsize/1024/1024))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
    99
    sys.stdout.write('new file size: %12d bytes (%6.1f MiB)\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   100
                     % (int(newsize), newsize/1024/1024))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   101
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   102
    shrink_percent = (oldsize - newsize) / oldsize * 100
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   103
    shrink_factor = oldsize / newsize
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   104
    sys.stdout.write('shrinkage: %.1f%% (%.1fx)\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   105
                     % (shrink_percent, shrink_factor))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   106
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   107
def main():
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   108
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   109
    # Unbuffer stdout for nice progress output.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   110
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   111
    write = sys.stdout.write
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   112
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   113
    parser = optparse.OptionParser(description=__doc__)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   114
    parser.add_option('-R', '--repository',
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   115
                      default=os.path.curdir,
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   116
                      metavar='REPO',
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   117
                      help='repository root directory [default: current dir]')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   118
    parser.add_option('--revlog',
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   119
                      metavar='FILE',
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   120
                      help='shrink FILE [default: REPO/hg/store/00manifest.i]')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   121
    (options, args) = parser.parse_args()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   122
    if args:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   123
        parser.error('too many arguments')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   124
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   125
    # Open the specified repository.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   126
    ui = ui_.ui()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   127
    repo = hg.repository(ui, options.repository)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   128
    if not repo.local():
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   129
        parser.error('not a local repository: %s' % options.repository)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   130
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   131
    if options.revlog is None:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   132
        indexfn = repo.sjoin('00manifest.i')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   133
    else:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   134
        if not options.revlog.endswith('.i'):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   135
            parser.error('--revlog option must specify the revlog index file '
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   136
                         '(*.i), not %s' % options.revlog)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   137
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   138
        indexfn = os.path.realpath(options.revlog)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   139
        store = repo.sjoin('')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   140
        if not indexfn.startswith(store):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   141
            parser.error('--revlog option must specify a revlog in %s, not %s'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   142
                         % (store, indexfn))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   143
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   144
    datafn = indexfn[:-2] + '.d'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   145
    if not os.path.exists(indexfn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   146
        parser.error('no such file: %s' % indexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   147
    if '00changelog' in indexfn:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   148
        parser.error('shrinking the changelog will corrupt your repository')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   149
    if not os.path.exists(datafn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   150
        # This is just a lazy shortcut because I can't be bothered to
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   151
        # handle all the special cases that entail from no .d file.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   152
        parser.error('%s does not exist: revlog not big enough '
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   153
                     'to be worth shrinking' % datafn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   154
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   155
    oldindexfn = indexfn + '.old'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   156
    olddatafn = datafn + '.old'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   157
    if os.path.exists(oldindexfn) or os.path.exists(olddatafn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   158
        parser.error('one or both of\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   159
                     '  %s\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   160
                     '  %s\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   161
                     'exists from a previous run; please clean up before '
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   162
                     'running again'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   163
                     % (oldindexfn, olddatafn))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   164
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   165
    write('shrinking %s\n' % indexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   166
    prefix = os.path.basename(indexfn)[:-1]
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   167
    (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn),
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   168
                                           prefix=prefix,
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   169
                                           suffix='.i')
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   170
    tmpdatafn = tmpindexfn[:-2] + '.d'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   171
    os.close(tmpfd)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   172
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   173
    r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), indexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   174
    r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), tmpindexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   175
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   176
    # Don't use repo.transaction(), because then things get hairy with
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   177
    # paths: some need to be relative to .hg, and some need to be
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   178
    # absolute.  Doing it this way keeps things simple: everything is an
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   179
    # absolute path.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   180
    lock = repo.lock(wait=False)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   181
    tr = transaction.transaction(sys.stderr.write,
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   182
                                 open,
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   183
                                 repo.sjoin('journal'))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   184
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   185
    try:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   186
        try:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   187
            order = toposort(r1)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   188
            writerevs(r1, r2, order, tr)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   189
            report(datafn, tmpdatafn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   190
            tr.close()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   191
        except:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   192
            # Abort transaction first, so we truncate the files before
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   193
            # deleting them.
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   194
            tr.abort()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   195
            if os.path.exists(tmpindexfn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   196
                os.unlink(tmpindexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   197
            if os.path.exists(tmpdatafn):
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   198
                os.unlink(tmpdatafn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   199
            raise
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   200
    finally:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   201
        lock.release()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   202
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   203
    os.link(indexfn, oldindexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   204
    os.link(datafn, olddatafn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   205
    os.rename(tmpindexfn, indexfn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   206
    os.rename(tmpdatafn, datafn)
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   207
    write('note: old revlog saved in:\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   208
          '  %s\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   209
          '  %s\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   210
          '(You can delete those files when you are satisfied that your\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   211
          'repository is still sane.  '
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   212
          'Running \'hg verify\' is strongly recommended.)\n'
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   213
          % (oldindexfn, olddatafn))
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   214
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   215
try:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   216
    main()
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   217
except KeyboardInterrupt:
f7d85980261c Add script to rewrite revlog to workaround lack of parent deltas.
Greg Ward <greg-hg@gerg.ca>
parents:
diff changeset
   218
    sys.exit("interrupted")