comparison contrib/shrink-revlog.py @ 10213:9e6848f352b0

contrib: use ui to write in shrink-revlog.py
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Thu, 07 Jan 2010 15:07:18 +0100
parents 69dca8574a6a
children 8111f9988c9d
comparison
equal deleted inserted replaced
10212:3ab391dd5ec5 10213:9e6848f352b0
20 import sys, os, tempfile 20 import sys, os, tempfile
21 import optparse 21 import optparse
22 from mercurial import ui as ui_, hg, revlog, transaction, node, util 22 from mercurial import ui as ui_, hg, revlog, transaction, node, util
23 from mercurial import changegroup 23 from mercurial import changegroup
24 24
25 def toposort(rl): 25 def toposort(ui, rl):
26 write = sys.stdout.write
27 26
28 children = {} 27 children = {}
29 root = [] 28 root = []
30 # build children and roots 29 # build children and roots
31 write('reading %d revs ' % len(rl)) 30 ui.write('reading %d revs ' % len(rl))
32 try: 31 try:
33 for i in rl: 32 for i in rl:
34 children[i] = [] 33 children[i] = []
35 parents = [p for p in rl.parentrevs(i) if p != node.nullrev] 34 parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
36 # in case of duplicate parents 35 # in case of duplicate parents
42 41
43 if len(parents) == 0: 42 if len(parents) == 0:
44 root.append(i) 43 root.append(i)
45 44
46 if i % 1000 == 0: 45 if i % 1000 == 0:
47 write('.') 46 ui.write('.')
48 finally: 47 finally:
49 write('\n') 48 ui.write('\n')
50 49
51 # XXX this is a reimplementation of the 'branchsort' topo sort 50 # XXX this is a reimplementation of the 'branchsort' topo sort
52 # algorithm in hgext.convert.convcmd... would be nice not to duplicate 51 # algorithm in hgext.convert.convcmd... would be nice not to duplicate
53 # the algorithm 52 # the algorithm
54 write('sorting ...') 53 ui.write('sorting ...')
55 visit = root 54 visit = root
56 ret = [] 55 ret = []
57 while visit: 56 while visit:
58 i = visit.pop(0) 57 i = visit.pop(0)
59 ret.append(i) 58 ret.append(i)
66 parents_unseen = [p for p in rl.parentrevs(c) 65 parents_unseen = [p for p in rl.parentrevs(c)
67 if p != node.nullrev and p in children] 66 if p != node.nullrev and p in children]
68 if len(parents_unseen) == 0: 67 if len(parents_unseen) == 0:
69 next.append(c) 68 next.append(c)
70 visit = next + visit 69 visit = next + visit
71 write('\n') 70 ui.write('\n')
72 return ret 71 return ret
73 72
74 def writerevs(r1, r2, order, tr): 73 def writerevs(ui, r1, r2, order, tr):
75 write = sys.stdout.write 74
76 write('writing %d revs ' % len(order)) 75 ui.write('writing %d revs ' % len(order))
77
78 count = [0] 76 count = [0]
79 def progress(*args): 77 def progress(*args):
80 if count[0] % 1000 == 0: 78 if count[0] % 1000 == 0:
81 write('.') 79 ui.write('.')
82 count[0] += 1 80 count[0] += 1
83 81
84 order = [r1.node(r) for r in order] 82 order = [r1.node(r) for r in order]
85 83
86 # this is a bit ugly, but it works 84 # this is a bit ugly, but it works
90 try: 88 try:
91 group = util.chunkbuffer(r1.group(order, lookup, progress)) 89 group = util.chunkbuffer(r1.group(order, lookup, progress))
92 chunkiter = changegroup.chunkiter(group) 90 chunkiter = changegroup.chunkiter(group)
93 r2.addgroup(chunkiter, unlookup, tr) 91 r2.addgroup(chunkiter, unlookup, tr)
94 finally: 92 finally:
95 write('\n') 93 ui.write('\n')
96 94
97 def report(olddatafn, newdatafn): 95 def report(ui, olddatafn, newdatafn):
98 oldsize = float(os.stat(olddatafn).st_size) 96 oldsize = float(os.stat(olddatafn).st_size)
99 newsize = float(os.stat(newdatafn).st_size) 97 newsize = float(os.stat(newdatafn).st_size)
100 98
101 # argh: have to pass an int to %d, because a float >= 2^32 99 # argh: have to pass an int to %d, because a float >= 2^32
102 # blows up under Python 2.5 or earlier 100 # blows up under Python 2.5 or earlier
103 sys.stdout.write('old file size: %12d bytes (%6.1f MiB)\n' 101 ui.write('old file size: %12d bytes (%6.1f MiB)\n'
104 % (int(oldsize), oldsize/1024/1024)) 102 % (int(oldsize), oldsize/1024/1024))
105 sys.stdout.write('new file size: %12d bytes (%6.1f MiB)\n' 103 ui.write('new file size: %12d bytes (%6.1f MiB)\n'
106 % (int(newsize), newsize/1024/1024)) 104 % (int(newsize), newsize/1024/1024))
107 105
108 shrink_percent = (oldsize - newsize) / oldsize * 100 106 shrink_percent = (oldsize - newsize) / oldsize * 100
109 shrink_factor = oldsize / newsize 107 shrink_factor = oldsize / newsize
110 sys.stdout.write('shrinkage: %.1f%% (%.1fx)\n' 108 ui.write('shrinkage: %.1f%% (%.1fx)\n' % (shrink_percent, shrink_factor))
111 % (shrink_percent, shrink_factor))
112 109
113 def main(): 110 def main():
114 111
115 # Unbuffer stdout for nice progress output. 112 # Unbuffer stdout for nice progress output.
116 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) 113 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
117 write = sys.stdout.write
118 114
119 parser = optparse.OptionParser(description=__doc__) 115 parser = optparse.OptionParser(description=__doc__)
120 parser.add_option('-R', '--repository', 116 parser.add_option('-R', '--repository',
121 default=os.path.curdir, 117 default=os.path.curdir,
122 metavar='REPO', 118 metavar='REPO',
166 ' %s\n' 162 ' %s\n'
167 'exists from a previous run; please clean up before ' 163 'exists from a previous run; please clean up before '
168 'running again' 164 'running again'
169 % (oldindexfn, olddatafn)) 165 % (oldindexfn, olddatafn))
170 166
171 write('shrinking %s\n' % indexfn) 167 ui.write('shrinking %s\n' % indexfn)
172 prefix = os.path.basename(indexfn)[:-1] 168 prefix = os.path.basename(indexfn)[:-1]
173 (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn), 169 (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn),
174 prefix=prefix, 170 prefix=prefix,
175 suffix='.i') 171 suffix='.i')
176 tmpdatafn = tmpindexfn[:-2] + '.d' 172 tmpdatafn = tmpindexfn[:-2] + '.d'
188 open, 184 open,
189 repo.sjoin('journal')) 185 repo.sjoin('journal'))
190 186
191 try: 187 try:
192 try: 188 try:
193 order = toposort(r1) 189 order = toposort(ui, r1)
194 writerevs(r1, r2, order, tr) 190 writerevs(ui, r1, r2, order, tr)
195 report(datafn, tmpdatafn) 191 report(ui, datafn, tmpdatafn)
196 tr.close() 192 tr.close()
197 except: 193 except:
198 # Abort transaction first, so we truncate the files before 194 # Abort transaction first, so we truncate the files before
199 # deleting them. 195 # deleting them.
200 tr.abort() 196 tr.abort()
208 204
209 os.link(indexfn, oldindexfn) 205 os.link(indexfn, oldindexfn)
210 os.link(datafn, olddatafn) 206 os.link(datafn, olddatafn)
211 os.rename(tmpindexfn, indexfn) 207 os.rename(tmpindexfn, indexfn)
212 os.rename(tmpdatafn, datafn) 208 os.rename(tmpdatafn, datafn)
213 write('note: old revlog saved in:\n' 209 ui.write('note: old revlog saved in:\n'
214 ' %s\n' 210 ' %s\n'
215 ' %s\n' 211 ' %s\n'
216 '(You can delete those files when you are satisfied that your\n' 212 '(You can delete those files when you are satisfied that your\n'
217 'repository is still sane. ' 213 'repository is still sane. '
218 'Running \'hg verify\' is strongly recommended.)\n' 214 'Running \'hg verify\' is strongly recommended.)\n'