/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1080 by Martin Pool
- test tool for converting history to weave files
1
#! /usr/bin/python
1267 by Martin Pool
- notes on conversion of existing history to weaves
2
#
1080 by Martin Pool
- test tool for converting history to weave files
3
# Copyright (C) 2005 Canonical Ltd
1267 by Martin Pool
- notes on conversion of existing history to weaves
4
#
1080 by Martin Pool
- test tool for converting history to weave files
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
1267 by Martin Pool
- notes on conversion of existing history to weaves
9
#
1080 by Martin Pool
- test tool for converting history to weave files
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
1267 by Martin Pool
- notes on conversion of existing history to weaves
14
#
1080 by Martin Pool
- test tool for converting history to weave files
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
"""Experiment in converting existing bzr branches to weaves."""
20
1267 by Martin Pool
- notes on conversion of existing history to weaves
21
# To make this properly useful
22
#
23
# 1. assign text version ids, and put those text versions into
24
#    the inventory as they're converted.
25
#
26
# 2. keep track of the previous version of each file, rather than
27
#    just using the last one imported
28
#
29
# 3. assign entry versions when files are added, renamed or moved.
30
#
31
# 4. when merged-in versions are observed, walk down through them
32
#    to discover everything, then commit bottom-up
33
#
34
# 5. track ancestry as things are merged in, and commit that in each
35
#    revision
36
#
37
# Perhaps it's best to first walk the whole graph and make a plan for
38
# what should be imported in what order?  Need a kind of topological
39
# sort of all revisions.  (Or do we, can we just before doing a revision
40
# see that all its parents have either been converted or abandoned?)
41
1315 by Martin Pool
- import file inventories in correct order
42
43
# Cannot import a revision until all its parents have been
44
# imported.  in other words, we can only import revisions whose
45
# parents have all been imported.  the first step must be to
46
# import a revision with no parents, of which there must be at
47
# least one.  (So perhaps it's useful to store forward pointers
48
# from a list of parents to their children?)
49
#
50
# Another (equivalent?) approach is to build up the ordered
51
# ancestry list for the last revision, and walk through that.  We
52
# are going to need that.
53
#
54
# We don't want to have to recurse all the way back down the list.
55
#
56
# Suppose we keep a queue of the revisions able to be processed at
57
# any point.  This starts out with all the revisions having no
58
# parents.
59
#
60
# This seems like a generally useful algorithm...
61
#
62
# The current algorithm is dumb (O(n**2)?) but will do the job, and
63
# takes less than a second on the bzr.dev branch.
64
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
65
# This currently does a kind of lazy conversion of file texts, where a
66
# new text is written in every version.  That's unnecessary but for
67
# the moment saves us having to worry about when files need new
68
# versions.
69
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
70
# TODO: Check that the working directory is clean before converting
71
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
72
1350 by Martin Pool
- set reasonable name_versions
73
if False:
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
74
    try:
75
        import psyco
76
        psyco.full()
77
    except ImportError:
78
        pass
1083 by Martin Pool
- add space to store revision-id in weave files
79
1080 by Martin Pool
- test tool for converting history to weave files
80
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
81
import os
1267 by Martin Pool
- notes on conversion of existing history to weaves
82
import tempfile
83
import hotshot, hotshot.stats
84
import sys
1132 by Martin Pool
- fix up logging for history2weaves tool
85
import logging
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
86
import shutil
1132 by Martin Pool
- fix up logging for history2weaves tool
87
1355 by Martin Pool
- write working inventory into final location
88
from bzrlib.branch import Branch, find_branch, BZR_BRANCH_FORMAT_5
1080 by Martin Pool
- test tool for converting history to weave files
89
from bzrlib.revfile import Revfile
90
from bzrlib.weave import Weave
91
from bzrlib.weavefile import read_weave, write_weave
92
from bzrlib.progress import ProgressBar
93
from bzrlib.atomicfile import AtomicFile
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
94
from bzrlib.xml4 import serializer_v4
95
from bzrlib.xml5 import serializer_v5
1307 by Martin Pool
- start walking through ancestors in conversion to weaves
96
from bzrlib.trace import mutter, note, warning, enable_default_logging
1326 by Martin Pool
- check inventory sha when loading old revisions
97
from bzrlib.osutils import sha_strings, sha_string
1337 by Martin Pool
- produce ancestry when converting versions
98
from bzrlib.commit import merge_ancestry_lines
1267 by Martin Pool
- notes on conversion of existing history to weaves
99
1080 by Martin Pool
- test tool for converting history to weave files
100
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
101
class Convert(object):
102
    def __init__(self):
1307 by Martin Pool
- start walking through ancestors in conversion to weaves
103
        self.converted_revs = set()
104
        self.absent_revisions = set()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
105
        self.text_count = 0
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
106
        self.revisions = {}
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
107
        self.inventories = {}
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
108
        self.convert()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
109
        
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
110
111
112
    def convert(self):
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
113
	if not os.path.exists('.bzr/allow-upgrade'):
114
	    raise Exception, "please create .bzr/allow-upgrade to indicate consent"
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
115
	self._backup_control_dir()
1358 by Martin Pool
- actually upgrade all of history
116
	note('starting upgrade')
117
	note('note: upgrade will be faster if all store files are ungzipped first')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
118
        self.pb = ProgressBar()
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
119
	if not os.path.isdir('.bzr/weaves'):
120
	    os.mkdir('.bzr/weaves')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
121
        self.inv_weave = Weave('__inventory')
122
        self.anc_weave = Weave('__ancestry')
1337 by Martin Pool
- produce ancestry when converting versions
123
        self.ancestries = {}
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
124
        # holds in-memory weaves for all files
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
125
        self.text_weaves = {}
1337 by Martin Pool
- produce ancestry when converting versions
126
        self.branch = Branch('.', relax_version_check=True)
1355 by Martin Pool
- write working inventory into final location
127
	os.remove(self.branch.controlfilename('branch-format'))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
128
	self._convert_working_inv()
1358 by Martin Pool
- actually upgrade all of history
129
        rev_history = self.branch.revision_history()
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
130
        # to_read is a stack holding the revisions we still need to process;
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
131
        # appending to it adds new highest-priority revisions
1319 by Martin Pool
- calculate and use file parents for importing texts
132
        self.known_revisions = set(rev_history)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
133
        self.to_read = [rev_history[-1]]
134
        while self.to_read:
135
            rev_id = self.to_read.pop()
136
            if (rev_id not in self.revisions
137
                and rev_id not in self.absent_revisions):
138
                self._load_one_rev(rev_id)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
139
        self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
140
        to_import = self._make_order()
1315 by Martin Pool
- import file inventories in correct order
141
        for i, rev_id in enumerate(to_import):
142
            self.pb.update('converting revision', i, len(to_import))
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
143
            self._convert_one_rev(rev_id)
1331 by Martin Pool
- write out new revisions after conversion
144
        self.pb.clear()
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
145
        note('upgraded to weaves:')
146
        note('  %6d revisions and inventories' % len(self.revisions))
147
        note('  %6d absent revisions removed' % len(self.absent_revisions))
148
        note('  %6d texts' % self.text_count)
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
149
        self._write_all_weaves()
1331 by Martin Pool
- write out new revisions after conversion
150
        self._write_all_revs()
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
151
	self._set_new_format()
152
	self._cleanup_spare_files()
153
154
155
    def _set_new_format(self):
1355 by Martin Pool
- write working inventory into final location
156
	f = self.branch.controlfile('branch-format', 'wb')
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
157
    	try:
1355 by Martin Pool
- write working inventory into final location
158
	    f.write(BZR_BRANCH_FORMAT_5)
159
	finally:
160
	    f.close()
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
161
		
1355 by Martin Pool
- write working inventory into final location
162
163
164
    def _cleanup_spare_files(self):
165
	for n in 'merged-patches', 'pending-merged-patches':
166
	    p = self.branch.controlfilename(n)
167
	    if not os.path.exists(p):
168
		continue
169
	    assert os.path.getsize(p) == 0
170
	    os.remove(p)
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
171
	os.remove('.bzr/allow-upgrade')
172
	shutil.rmtree('.bzr/inventory-store')
173
	shutil.rmtree('.bzr/text-store')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
174
175
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
176
    def _backup_control_dir(self):
177
	shutil.copytree('.bzr', '.bzr.backup')
178
	note('.bzr has been backed up to .bzr.backup')
179
	note('if conversion fails, you can move this directory back to .bzr')
180
	note('if it succeeds, you can remove this directory if you wish')
181
182
183
    def _convert_working_inv(self):
184
	branch = self.branch
185
	inv = serializer_v4.read_inventory(branch.controlfile('inventory', 'rb'))
1355 by Martin Pool
- write working inventory into final location
186
	serializer_v5.write_inventory(inv, branch.controlfile('inventory', 'wb'))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
187
188
189
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
190
    def _write_all_weaves(self):
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
191
        write_a_weave(self.inv_weave, '.bzr/inventory.weave')
192
        write_a_weave(self.anc_weave, '.bzr/ancestry.weave')
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
193
        i = 0
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
194
        try:
195
            for file_id, file_weave in self.text_weaves.items():
196
                self.pb.update('writing weave', i, len(self.text_weaves))
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
197
                write_a_weave(file_weave, '.bzr/weaves/%s.weave' % file_id)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
198
                i += 1
199
        finally:
200
            self.pb.clear()
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
201
1331 by Martin Pool
- write out new revisions after conversion
202
203
    def _write_all_revs(self):
204
        """Write all revisions out in new form."""
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
205
	shutil.rmtree('.bzr/revision-store')
206
	os.mkdir('.bzr/revision-store')
1331 by Martin Pool
- write out new revisions after conversion
207
        try:
208
            for i, rev_id in enumerate(self.converted_revs):
209
                self.pb.update('write revision', i, len(self.converted_revs))
1357 by Martin Pool
- require marker file to do upgrade so as not to clobber something important
210
                f = file('.bzr/revision-store/%s' % rev_id, 'wb')
1331 by Martin Pool
- write out new revisions after conversion
211
                try:
212
                    serializer_v5.write_revision(self.revisions[rev_id], f)
213
                finally:
214
                    f.close()
215
        finally:
216
            self.pb.clear()
1332 by Martin Pool
- clean up code that writes out weave results
217
1331 by Martin Pool
- write out new revisions after conversion
218
            
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
219
    def _load_one_rev(self, rev_id):
220
        """Load a revision object into memory.
221
222
        Any parents not either loaded or abandoned get queued to be
223
        loaded."""
224
        self.pb.update('loading revision',
1315 by Martin Pool
- import file inventories in correct order
225
                       len(self.revisions),
1319 by Martin Pool
- calculate and use file parents for importing texts
226
                       len(self.known_revisions))
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
227
        if rev_id not in self.branch.revision_store:
228
            self.pb.clear()
229
            note('revision {%s} not present in branch; '
230
                 'will not be converted',
231
                 rev_id)
232
            self.absent_revisions.add(rev_id)
233
        else:
234
            rev_xml = self.branch.revision_store[rev_id].read()
235
            rev = serializer_v4.read_revision_from_string(rev_xml)
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
236
            for parent_id in rev.parent_ids:
1319 by Martin Pool
- calculate and use file parents for importing texts
237
                self.known_revisions.add(parent_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
238
                self.to_read.append(parent_id)
239
            self.revisions[rev_id] = rev
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
240
            old_inv_xml = self.branch.inventory_store[rev_id].read()
241
            inv = serializer_v4.read_inventory_from_string(old_inv_xml)
1326 by Martin Pool
- check inventory sha when loading old revisions
242
            assert rev.inventory_sha1 == sha_string(old_inv_xml)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
243
            self.inventories[rev_id] = inv
244
        
245
246
    def _convert_one_rev(self, rev_id):
247
        """Convert revision and all referenced objects to new format."""
248
        rev = self.revisions[rev_id]
249
        inv = self.inventories[rev_id]
1337 by Martin Pool
- produce ancestry when converting versions
250
        for parent_id in rev.parent_ids[:]:
251
            if parent_id in self.absent_revisions:
252
                rev.parent_ids.remove(parent_id)
253
                self.pb.clear()
254
                note('remove {%s} as parent of {%s}', parent_id, rev_id)
1320 by Martin Pool
- write updated inventory into weave
255
        self._convert_revision_contents(rev, inv)
256
        # the XML is now updated with text versions
1316 by Martin Pool
- upgrade format of inventories as they're converted
257
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
258
        new_inv_sha1 = sha_string(new_inv_xml)
1337 by Martin Pool
- produce ancestry when converting versions
259
        self.inv_weave.add(rev_id, rev.parent_ids,
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
260
                           new_inv_xml.splitlines(True),
261
                           new_inv_sha1)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
262
        # TODO: Upgrade revision XML and write that out
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
263
        rev.inventory_sha1 = new_inv_sha1
1337 by Martin Pool
- produce ancestry when converting versions
264
        self._make_rev_ancestry(rev)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
265
        self.converted_revs.add(rev_id)
266
267
1337 by Martin Pool
- produce ancestry when converting versions
268
    def _make_rev_ancestry(self, rev):
269
        rev_id = rev.revision_id
270
        for parent_id in rev.parent_ids:
271
            assert parent_id in self.converted_revs
1340 by Martin Pool
- conversion to weave computes ancestries using weave mash
272
        if rev.parent_ids:
273
            lines = list(self.anc_weave.mash_iter(rev.parent_ids))
274
        else:
275
            lines = []
276
        lines.append(rev_id + '\n')
277
        if __debug__:
278
            parent_ancestries = [self.ancestries[p] for p in rev.parent_ids]
279
            new_lines = merge_ancestry_lines(rev_id, parent_ancestries)
280
            assert set(lines) == set(new_lines)
281
            self.ancestries[rev_id] = new_lines
282
        self.anc_weave.add(rev_id, rev.parent_ids, lines)
1337 by Martin Pool
- produce ancestry when converting versions
283
284
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
285
    def _convert_revision_contents(self, rev, inv):
286
        """Convert all the files within a revision.
287
288
        Also upgrade the inventory to refer to the text revision ids."""
289
        rev_id = rev.revision_id
1319 by Martin Pool
- calculate and use file parents for importing texts
290
        mutter('converting texts of revision {%s}',
291
               rev_id)
1332 by Martin Pool
- clean up code that writes out weave results
292
        for file_id in inv:
293
            ie = inv[file_id]
1350 by Martin Pool
- set reasonable name_versions
294
	    self._set_name_version(rev, ie)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
295
            if ie.kind != 'file':
296
                continue
1319 by Martin Pool
- calculate and use file parents for importing texts
297
            self._convert_file_version(rev, ie)
1350 by Martin Pool
- set reasonable name_versions
298
299
300
    def _set_name_version(self, rev, ie):
301
	"""Set name version for a file.
302
303
	Done in a slightly lazy way: if the file is renamed or in a merge revision
304
	it gets a new version, otherwise the same as before.
305
	"""
306
	file_id = ie.file_id
307
	if len(rev.parent_ids) != 1:
308
	    ie.name_version = rev.revision_id
309
	else:
310
	    old_inv = self.inventories[rev.parent_ids[0]]
311
	    if not old_inv.has_id(file_id):
312
		ie.name_version = rev.revision_id
313
	    else:
314
		old_ie = old_inv[file_id]
315
		if (old_ie.parent_id != ie.parent_id
316
		    or old_ie.name != ie.name):
317
		    ie.name_version = rev.revision_id
318
		else:
319
		    ie.name_version = old_ie.name_version
320
1319 by Martin Pool
- calculate and use file parents for importing texts
321
322
323
    def _convert_file_version(self, rev, ie):
324
        """Convert one version of one file.
325
326
        The file needs to be added into the weave if it is a merge
327
        of >=2 parents or if it's changed from its parent.
328
        """
329
        file_id = ie.file_id
330
        rev_id = rev.revision_id
331
        w = self.text_weaves.get(file_id)
332
        if w is None:
333
            w = Weave(file_id)
334
            self.text_weaves[file_id] = w
335
        file_lines = self.branch.text_store[ie.text_id].readlines()
336
        assert sha_strings(file_lines) == ie.text_sha1
337
        assert sum(map(len, file_lines)) == ie.text_size
338
        file_parents = []
339
        text_changed = False
340
        for parent_id in rev.parent_ids:
1337 by Martin Pool
- produce ancestry when converting versions
341
            ##if parent_id in self.absent_revisions:
342
            ##    continue
343
            assert parent_id in self.converted_revs, \
344
                   'parent {%s} not converted' % parent_id
1319 by Martin Pool
- calculate and use file parents for importing texts
345
            parent_inv = self.inventories[parent_id]
346
            if parent_inv.has_id(file_id):
347
                parent_ie = parent_inv[file_id]
348
                old_text_version = parent_ie.text_version
349
                assert old_text_version in self.converted_revs 
350
                if old_text_version not in file_parents:
351
                    file_parents.append(old_text_version)
352
                if parent_ie.text_sha1 != ie.text_sha1:
353
                    text_changed = True
354
        if len(file_parents) != 1 or text_changed:
1325 by Martin Pool
- conversion to weave tries to avoid repeated SHA calculation
355
            w.add(rev_id, file_parents, file_lines, ie.text_sha1)
1350 by Martin Pool
- set reasonable name_versions
356
            ie.text_version = rev_id
1332 by Martin Pool
- clean up code that writes out weave results
357
            self.text_count += 1
1330 by Martin Pool
- fiddle with trace
358
            ##mutter('import text {%s} of {%s}',
359
            ##       ie.text_id, file_id)
1319 by Martin Pool
- calculate and use file parents for importing texts
360
        else:
1330 by Martin Pool
- fiddle with trace
361
            ##mutter('text of {%s} unchanged from parent', file_id)            
1319 by Martin Pool
- calculate and use file parents for importing texts
362
            ie.text_version = file_parents[0]
363
        del ie.text_id
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
364
                   
1310 by Martin Pool
- compute order to import revisions
365
366
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
367
    def _make_order(self):
1310 by Martin Pool
- compute order to import revisions
368
        """Return a suitable order for importing revisions.
369
370
        The order must be such that an revision is imported after all
371
        its (present) parents.
372
        """
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
373
        todo = set(self.revisions.keys())
374
        done = self.absent_revisions.copy()
1310 by Martin Pool
- compute order to import revisions
375
        o = []
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
376
        while todo:
377
            # scan through looking for a revision whose parents
378
            # are all done
1310 by Martin Pool
- compute order to import revisions
379
            for rev_id in sorted(list(todo)):
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
380
                rev = self.revisions[rev_id]
1313 by Martin Pool
- rename to Revision.parent_ids to avoid confusion with old usage
381
                parent_ids = set(rev.parent_ids)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
382
                if parent_ids.issubset(done):
383
                    # can take this one now
1310 by Martin Pool
- compute order to import revisions
384
                    o.append(rev_id)
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
385
                    todo.remove(rev_id)
386
                    done.add(rev_id)
1315 by Martin Pool
- import file inventories in correct order
387
        return o
1309 by Martin Pool
- first cut at tsort to make order to bring in revisions
388
                
389
1332 by Martin Pool
- clean up code that writes out weave results
390
def write_a_weave(weave, filename):
391
    inv_wf = file(filename, 'wb')
1080 by Martin Pool
- test tool for converting history to weave files
392
    try:
1087 by Martin Pool
- add a tool script to convert past history into weaves
393
        write_weave(weave, inv_wf)
1080 by Martin Pool
- test tool for converting history to weave files
394
    finally:
395
        inv_wf.close()
396
1087 by Martin Pool
- add a tool script to convert past history into weaves
397
    
1080 by Martin Pool
- test tool for converting history to weave files
398
399
400
def profile_convert(): 
401
    prof_f = tempfile.NamedTemporaryFile()
402
403
    prof = hotshot.Profile(prof_f.name)
404
1300 by Martin Pool
- refactor weave upgrade into a MethodObject
405
    prof.runcall(Convert) 
1080 by Martin Pool
- test tool for converting history to weave files
406
    prof.close()
407
408
    stats = hotshot.stats.load(prof_f.name)
1267 by Martin Pool
- notes on conversion of existing history to weaves
409
    ##stats.strip_dirs()
1080 by Martin Pool
- test tool for converting history to weave files
410
    stats.sort_stats('time')
1267 by Martin Pool
- notes on conversion of existing history to weaves
411
    # XXX: Might like to write to stderr or the trace file instead but
412
    # print_stats seems hardcoded to stdout
1330 by Martin Pool
- fiddle with trace
413
    stats.print_stats(100)
1318 by Martin Pool
- pull texts into weaves in a fairly lazy way
414
415
1350 by Martin Pool
- set reasonable name_versions
416
if __name__ == '__main__':
417
    enable_default_logging()
1080 by Martin Pool
- test tool for converting history to weave files
418
1350 by Martin Pool
- set reasonable name_versions
419
    if '-p' in sys.argv[1:]:
420
	profile_convert()
421
    else:
422
	Convert()