/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
703 by Martin Pool
- split out a new 'bzr upgrade' command separate from
1
# Copyright (C) 2004, 2005 by Martin Pool
2
# Copyright (C) 2005 by Canonical Ltd
3
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
19
20
21
def upgrade(branch):
22
    """
23
    Upgrade branch to current format.
24
25
    This causes objects to be rewritten into the current format.
26
27
    If they change, their SHA-1 will of course change, which might
28
    break any later signatures, or backreferences that check the
29
    SHA-1.
30
    """
31
    import sys
32
33
    from bzrlib.trace import mutter
34
    from bzrlib.errors import BzrCheckError
35
    from bzrlib.progress import ProgressBar
36
37
    branch.lock_write()
38
39
    try:
40
        pb = ProgressBar(show_spinner=True)
41
        last_ptr = None
42
        checked_revs = {}
43
44
        history = branch.revision_history()
45
        revno = 0
46
        revcount = len(history)
47
48
        updated_revisions = []
49
50
        # Set to True in the case that the previous revision entry
51
        # was updated, since this will affect future revision entries
52
        updated_previous_revision = False
53
54
        for rid in history:
55
            revno += 1
56
            pb.update('upgrading revision', revno, revcount)
57
            mutter('    revision {%s}' % rid)
58
            rev = branch.get_revision(rid)
59
            if rev.revision_id != rid:
60
                raise BzrCheckError('wrong internal revision id in revision {%s}' % rid)
61
            if rev.precursor != last_ptr:
62
                raise BzrCheckError('mismatched precursor in revision {%s}' % rid)
63
            last_ptr = rid
64
            if rid in checked_revs:
65
                raise BzrCheckError('repeated revision {%s}' % rid)
66
            checked_revs[rid] = True
67
68
            ## TODO: Check all the required fields are present on the revision.
69
70
            updated = False
71
            if rev.inventory_sha1:
72
                #mutter('    checking inventory hash {%s}' % rev.inventory_sha1)
73
                inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
74
                if inv_sha1 != rev.inventory_sha1:
75
                    raise BzrCheckError('Inventory sha1 hash doesn\'t match'
76
                        ' value in revision {%s}' % rid)
77
            else:
78
                inv_sha1 = branch.get_inventory_sha1(rev.inventory_id)
79
                rev.inventory_sha1 = inv_sha1
80
                updated = True
81
82
            if rev.precursor:
83
                if rev.precursor_sha1:
84
                    precursor_sha1 = branch.get_revision_sha1(rev.precursor)
85
                    if updated_previous_revision: 
86
                        # we don't expect the hashes to match, because
87
                        # we had to modify the previous revision_history entry.
88
                        rev.precursor_sha1 = precursor_sha1
89
                        updated = True
90
                    else:
91
                        #mutter('    checking precursor hash {%s}' % rev.precursor_sha1)
92
                        if rev.precursor_sha1 != precursor_sha1:
93
                            raise BzrCheckError('Precursor sha1 hash doesn\'t match'
94
                                ' value in revision {%s}' % rid)
95
                else:
96
                    precursor_sha1 = branch.get_revision_sha1(rev.precursor)
97
                    rev.precursor_sha1 = precursor_sha1
98
                    updated = True
99
100
            if updated:
101
                updated_previous_revision = True
102
                # We had to update this revision entries hashes
103
                # Now we need to write out a new value
104
                # This is a little bit invasive, since we are *rewriting* a
105
                # revision entry. I'm not supremely happy about it, but
106
                # there should be *some* way of making old entries have
107
                # the full meta information.
108
                import tempfile, os, errno
109
                rev_tmp = tempfile.TemporaryFile()
110
                rev.write_xml(rev_tmp)
111
                rev_tmp.seek(0)
112
113
                tmpfd, tmp_path = tempfile.mkstemp(prefix=rid, suffix='.gz',
114
                    dir=branch.controlfilename('revision-store'))
115
                os.close(tmpfd)
116
                def special_rename(p1, p2):
117
                    if sys.platform == 'win32':
118
                        try:
119
                            os.remove(p2)
120
                        except OSError, e:
121
                            if e.errno != errno.ENOENT:
122
                                raise
123
                    os.rename(p1, p2)
124
125
                try:
126
                    # TODO: We may need to handle the case where the old revision
127
                    # entry was not compressed (and thus did not end with .gz)
128
129
                    # Remove the old revision entry out of the way
130
                    rev_path = branch.controlfilename(['revision-store', rid+'.gz'])
131
                    special_rename(rev_path, tmp_path)
132
                    branch.revision_store.add(rev_tmp, rid) # Add the new one
133
                    os.remove(tmp_path) # Remove the old name
134
                    mutter('    Updated revision entry {%s}' % rid)
135
                except:
136
                    # On any exception, restore the old entry
137
                    special_rename(tmp_path, rev_path)
138
                    raise
139
                rev_tmp.close()
140
                updated_revisions.append(rid)
141
            else:
142
                updated_previous_revision = False
143
144
    finally:
145
        branch.unlock()
146
147
    pb.clear()
148
149
    if updated_revisions:
150
        print '%d revisions updated to current format' % len(updated_revisions)