~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to tools/history2weaves.py

  • Committer: Martin Pool
  • Date: 2005-09-16 09:19:54 UTC
  • Revision ID: mbp@sourcefrog.net-20050916091954-aee6d7be00db6354
- more docs in commit code

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#! /usr/bin/python
2
 
 
 
2
#
3
3
# Copyright (C) 2005 Canonical Ltd
4
 
 
 
4
#
5
5
# This program is free software; you can redistribute it and/or modify
6
6
# it under the terms of the GNU General Public License as published by
7
7
# the Free Software Foundation; either version 2 of the License, or
8
8
# (at your option) any later version.
9
 
 
 
9
#
10
10
# This program is distributed in the hope that it will be useful,
11
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
13
# GNU General Public License for more details.
14
 
 
 
14
#
15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
19
"""Experiment in converting existing bzr branches to weaves."""
20
20
 
21
 
try:
22
 
    import psyco
23
 
    psyco.full()
24
 
except ImportError:
25
 
    pass
26
 
 
27
 
 
 
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
 
 
42
if False:
 
43
    try:
 
44
        import psyco
 
45
        psyco.full()
 
46
    except ImportError:
 
47
        pass
 
48
 
 
49
 
 
50
import tempfile
 
51
import hotshot, hotshot.stats
 
52
import sys
28
53
import logging
 
54
import time
29
55
 
30
 
import bzrlib.branch
 
56
from bzrlib.branch import Branch, find_branch
31
57
from bzrlib.revfile import Revfile
32
58
from bzrlib.weave import Weave
33
59
from bzrlib.weavefile import read_weave, write_weave
34
60
from bzrlib.progress import ProgressBar
35
61
from bzrlib.atomicfile import AtomicFile
 
62
from bzrlib.xml4 import serializer_v4
 
63
from bzrlib.xml5 import serializer_v5
36
64
import bzrlib.trace
37
 
import tempfile
38
 
import hotshot, hotshot.stats
39
 
import sys
40
 
 
41
 
def convert():
42
 
    bzrlib.trace.enable_default_logging()
43
 
 
44
 
    pb = ProgressBar()
45
 
 
46
 
    inv_weave = Weave()
47
 
 
48
 
    last_text_sha = {}
49
 
 
50
 
    # holds in-memory weaves for all files
51
 
    text_weaves = {}
52
 
 
53
 
    b = bzrlib.branch.find_branch('.')
54
 
 
55
 
    revno = 1
56
 
    rev_history = b.revision_history()
57
 
    last_idx = None
58
 
    inv_parents = []
59
 
    text_count = 0
60
 
    
61
 
    for rev_id in rev_history:
62
 
        pb.update('converting revision', revno, len(rev_history))
63
 
        
64
 
        inv_xml = b.get_inventory_xml(rev_id).readlines()
65
 
 
66
 
        new_idx = inv_weave.add(rev_id, inv_parents, inv_xml)
 
65
 
 
66
 
 
67
 
 
68
class Convert(object):
 
69
    def __init__(self):
 
70
        self.total_revs = 0
 
71
        self.converted_revs = 0
 
72
        self.text_count = 0
 
73
        self.convert()
 
74
 
 
75
 
 
76
 
 
77
    def convert(self):
 
78
        bzrlib.trace.enable_default_logging()
 
79
        self.pb = ProgressBar()
 
80
        self.inv_weave = Weave('__inventory')
 
81
        self.anc_weave = Weave('__ancestry')
 
82
 
 
83
        last_text_sha = {}
 
84
 
 
85
        # holds in-memory weaves for all files
 
86
        text_weaves = {}
 
87
 
 
88
        b = self.branch = Branch('.', relax_version_check=True)
 
89
 
 
90
        revno = 1
 
91
        rev_history = b.revision_history()
 
92
        last_idx = None
 
93
        inv_parents = []
 
94
 
 
95
        # todo is a stack holding the revisions we still need to process;
 
96
        # appending to it adds new highest-priority revisions
 
97
        todo = rev_history[:]
 
98
        todo.reverse()
 
99
        self.total_revs = len(todo)
 
100
 
 
101
        while todo:
 
102
            self._convert_one_rev(todo.pop())
 
103
 
 
104
        self.pb.clear()
 
105
        print 'upgraded to weaves:'
 
106
        print '  %6d revisions and inventories' % self.converted_revs
 
107
        print '  %6d texts' % self.text_count
 
108
 
 
109
        self._write_all_weaves()
 
110
 
 
111
 
 
112
    def _write_all_weaves(self):
 
113
        i = 0
 
114
        return ############################################
 
115
        # TODO: commit them all atomically at the end, not one by one
 
116
        write_atomic_weave(self.inv_weave, 'weaves/inventory.weave')
 
117
        write_atomic_weave(self.anc_weave, 'weaves/ancestry.weave')
 
118
        for file_id, file_weave in text_weaves.items():
 
119
            self.pb.update('writing weave', i, len(text_weaves))
 
120
            write_atomic_weave(file_weave, 'weaves/%s.weave' % file_id)
 
121
            i += 1
 
122
 
 
123
        self.pb.clear()
 
124
 
 
125
        
 
126
    def _convert_one_rev(self, rev_id):
 
127
        self._bump_progress()
 
128
        b = self.branch
 
129
        rev_xml = b.revision_store[rev_id].read()
 
130
        inv_xml = b.inventory_store[rev_id].read()
 
131
 
 
132
        rev = serializer_v4.read_revision_from_string(rev_xml)
 
133
        inv = serializer_v4.read_inventory_from_string(inv_xml)
 
134
        
 
135
        return ##########################################
 
136
 
 
137
        new_idx = self.inv_weave.add(rev_id, inv_parents, inv_xml)
67
138
        inv_parents = [new_idx]
68
139
 
69
140
        tree = b.revision_tree(rev_id)
86
157
            # revision then make a new weave; else find the old one
87
158
            if file_id not in text_weaves:
88
159
                text_weaves[file_id] = Weave()
89
 
                
 
160
 
90
161
            w = text_weaves[file_id]
91
162
 
92
163
            # base the new text version off whatever was last
102
173
            text_count += 1
103
174
 
104
175
        revno += 1
105
 
 
106
 
    pb.clear()
107
 
    print '%6d revisions and inventories' % revno
108
 
    print '%6d texts' % text_count
109
 
 
110
 
    i = 0
111
 
    # TODO: commit them all atomically at the end, not one by one
112
 
    write_atomic_weave(inv_weave, 'weaves/inventory.weave')
113
 
    for file_id, file_weave in text_weaves.items():
114
 
        pb.update('writing weave', i, len(text_weaves))
115
 
        write_atomic_weave(file_weave, 'weaves/%s.weave' % file_id)
116
 
        i += 1
117
 
 
118
 
    pb.clear()
 
176
        
 
177
    def _bump_progress(self):
 
178
        self.converted_revs += 1
 
179
        self.pb.update('converting revisions',
 
180
                       self.converted_revs,
 
181
                       self.total_revs)
119
182
 
120
183
 
121
184
def write_atomic_weave(weave, filename):
134
197
 
135
198
    prof = hotshot.Profile(prof_f.name)
136
199
 
137
 
    prof.runcall(convert) 
 
200
    prof.runcall(Convert) 
138
201
    prof.close()
139
202
 
140
203
    stats = hotshot.stats.load(prof_f.name)
141
 
    #stats.strip_dirs()
 
204
    ##stats.strip_dirs()
142
205
    stats.sort_stats('time')
143
 
    ## XXX: Might like to write to stderr or the trace file instead but
144
 
    ## print_stats seems hardcoded to stdout
 
206
    # XXX: Might like to write to stderr or the trace file instead but
 
207
    # print_stats seems hardcoded to stdout
145
208
    stats.print_stats(20)
146
209
            
147
210
 
148
211
if '-p' in sys.argv[1:]:
149
212
    profile_convert()
150
213
else:
151
 
    convert()
 
214
    Convert()
152
215