1
3
# Copyright (C) 2005 Canonical Ltd
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
5
7
# the Free Software Foundation; either version 2 of the License, or
6
8
# (at your option) any later version.
8
10
# This program is distributed in the hope that it will be useful,
9
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
13
# GNU General Public License for more details.
13
15
# You should have received a copy of the GNU General Public License
14
16
# along with this program; if not, write to the Free Software
15
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""bzr upgrade logic."""
19
# change upgrade from .bzr to create a '.bzr-new', then do a bait and switch.
22
from bzrlib.bzrdir import ConvertBzrDir4To5, ConvertBzrDir5To6, BzrDir, BzrDirFormat4, BzrDirFormat5, BzrDirFormat
23
import bzrlib.errors as errors
24
from bzrlib.transport import get_transport
25
import bzrlib.ui as ui
28
class Convert(object):
30
def __init__(self, url, format):
32
self.bzrdir = BzrDir.open_unsupported(url)
33
if self.bzrdir.root_transport.is_readonly():
34
raise errors.UpgradeReadonly
35
self.transport = self.bzrdir.root_transport
36
self.pb = ui.ui_factory.nested_progress_bar()
44
branch = self.bzrdir.open_branch()
45
if branch.bzrdir.root_transport.base != \
46
self.bzrdir.root_transport.base:
47
self.pb.note("This is a checkout. The branch (%s) needs to be "
48
"upgraded separately.",
49
branch.bzrdir.root_transport.base)
50
except errors.NotBranchError:
52
if not self.bzrdir.needs_format_conversion(self.format):
53
raise errors.UpToDateFormat(self.bzrdir._format)
54
if not self.bzrdir.can_convert_format():
55
raise errors.BzrError("cannot upgrade from branch format %s" %
57
if self.format is None:
58
target_format = BzrDirFormat.get_default_format()
60
target_format = self.format
61
self.bzrdir.check_conversion_target(target_format)
62
self.pb.note('starting upgrade of %s', self.transport.base)
63
self._backup_control_dir()
64
while self.bzrdir.needs_format_conversion(self.format):
65
converter = self.bzrdir._format.get_converter(self.format)
66
self.bzrdir = converter.convert(self.bzrdir, self.pb)
67
self.pb.note("finished")
69
def _backup_control_dir(self):
70
self.pb.note('making backup of tree history')
71
self.transport.copy_tree('.bzr', '.bzr.backup')
72
self.pb.note('%s.bzr has been backed up to %s.bzr.backup',
75
self.pb.note('if conversion fails, you can move this directory back to .bzr')
76
self.pb.note('if it succeeds, you can remove this directory if you wish')
78
def upgrade(url, format=None):
79
"""Upgrade to format, or the default bzrdir format if not supplied."""
19
"""Experiment in converting existing bzr branches to weaves."""
31
from bzrlib.revfile import Revfile
32
from bzrlib.weave import Weave
33
from bzrlib.weavefile import read_weave, write_weave
34
from bzrlib.progress import ProgressBar
35
from bzrlib.atomicfile import AtomicFile
38
import hotshot, hotshot.stats
42
bzrlib.trace.enable_default_logging()
50
# holds in-memory weaves for all files
53
b = bzrlib.branch.find_branch('.')
56
rev_history = b.revision_history()
61
for rev_id in rev_history:
62
pb.update('converting revision', revno, len(rev_history))
64
inv_xml = b.get_inventory_xml(rev_id).readlines()
66
new_idx = inv_weave.add(rev_id, inv_parents, inv_xml)
67
inv_parents = [new_idx]
69
tree = b.revision_tree(rev_id)
72
# for each file in the inventory, put it into its own revfile
77
if last_text_sha.get(file_id) == ie.text_sha1:
80
last_text_sha[file_id] = ie.text_sha1
82
# new text (though possibly already stored); need to store it
83
text_lines = tree.get_file(file_id).readlines()
85
# if the file's created for the first time in this
86
# revision then make a new weave; else find the old one
87
if file_id not in text_weaves:
88
text_weaves[file_id] = Weave()
90
w = text_weaves[file_id]
92
# base the new text version off whatever was last
93
# (actually it'd be better to track this, to allow for
94
# files that are deleted and then reappear)
101
w.add(rev_id, parents, text_lines)
107
print '%6d revisions and inventories' % revno
108
print '%6d texts' % text_count
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)
121
def write_atomic_weave(weave, filename):
122
inv_wf = AtomicFile(filename)
124
write_weave(weave, inv_wf)
132
def profile_convert():
133
prof_f = tempfile.NamedTemporaryFile()
135
prof = hotshot.Profile(prof_f.name)
137
prof.runcall(convert)
140
stats = hotshot.stats.load(prof_f.name)
142
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
145
stats.print_stats(20)
148
if '-p' in sys.argv[1:]: