Merge lp:~bzr/bzr/smooth-upgrades into lp:~bzr/bzr/trunk-old

Proposed by Ian Clatworthy
Status: Merged
Merge reported by: Vincent Ladeuil
Merged at revision: not available
Proposed branch: lp:~bzr/bzr/smooth-upgrades
Merge into: lp:~bzr/bzr/trunk-old
Diff against target: 561 lines (has conflicts)
Text conflict in NEWS
To merge this branch: bzr merge lp:~bzr/bzr/smooth-upgrades
Reviewer Review Type Date Requested Status
Martin Pool Needs Information
Review via email: mp+8921@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ian Clatworthy (ian-clatworthy) wrote :

This patch adds numerous enhancements to the upgrade command to make upgrading a lot smoother than it currently is. In particular, it now upgrades dependent branches when a shared repository is specified. Based on feedback provided on the mailing list a few months back, it now also supports several new options:

* --dry-run for showing what will happen

* --clean to remove the backup.dir directory on successful completion

* --pack to pack the repository on successful completion.

There's room to make things even nicer still but I think this patch is large enough as is. I'd also like to get these changes landed soon to encourage those of us running Bazaar's trunk to get as many branches as possible converted to 2a prior to the Bazaar 2.0 release.

Revision history for this message
Aaron Bentley (abentley) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I think you should specify using=True to repo.find_branches. Branches
which aren't using the shared repository aren't really part of it even
if they're inside its directory, and may be in an incompatible format.

Aaron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkpgAO8ACgkQ0F+nu1YWqI1dTACfdxd519YTqoOuTz1OOa9zjtjY
Ot8Ani+XpR4URG8cbbbh5sBDWVr+/t6H
=7UNy
-----END PGP SIGNATURE-----

Revision history for this message
Robert Collins (lifeless) wrote :

On Fri, 2009-07-17 at 02:45 +0000, Ian Clatworthy wrote:
> Ian Clatworthy has proposed merging lp:~bzr/bzr/smooth-upgrades into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
>
> This patch adds numerous enhancements to the upgrade command to make upgrading a lot smoother than it currently is. In particular, it now upgrades dependent branches when a shared repository is specified. Based on feedback provided on the mailing list a few months back, it now also supports several new options:
>
> * --dry-run for showing what will happen
>
> * --clean to remove the backup.dir directory on successful completion

I think these are useful

> * --pack to pack the repository on successful completion.

This isn't needed; bzr will autopack if packing helps.

> There's room to make things even nicer still but I think this patch is large enough as is. I'd also like to get these changes landed soon to encourage those of us running Bazaar's trunk to get as many branches as possible converted to 2a prior to the Bazaar 2.0 release.

-Rob

Revision history for this message
Martin Pool (mbp) wrote :
Download full text (22.4 KiB)

=== modified file 'NEWS'
--- NEWS 2009-07-15 19:06:39 +0000
+++ NEWS 2009-07-17 02:29:14 +0000
@@ -19,6 +19,17 @@
 * ``merge --interactive`` applies a user-selected portion of the merge. The UI
   is similar to ``shelve``. (Aaron Bentley)

+* ``upgrade`` now upgrades dependent branches when a shared repository is
+ specified. It also supports several new options:
+
+ * --dry-run for showing what will happen
+
+ * --clean to remove the backup.dir directory on successful completion
+
+ * --pack to pack the repository on successful completion.
+
+ (Ian Clatworthy)
+

I'd put the options in double-backticks too.

You might also find some bug numbers corresponding to these...

 Bug Fixes
 *********

=== modified file 'bzrlib/builtins.py'
--- bzrlib/builtins.py 2009-07-15 07:32:26 +0000
+++ bzrlib/builtins.py 2009-07-17 02:29:14 +0000
@@ -3122,27 +3122,60 @@

 class cmd_upgrade(Command):
- """Upgrade branch storage to current format.
-
- The check command or bzr developers may sometimes advise you to run
- this command. When the default format has changed you may also be warned
- during other operations to upgrade.
+ """Upgrade a repository, branch or working tree to a newer format.
+
+ The check command or Bazaar developers may sometimes advise you to run
+ this command. When the default format has changed after a major new
+ release of Bazaar, you may also be warned during other operations
+ that you should upgrade.

This bit about 'the check command' almost sounds like a mis-copy from
cmd_reconcile. Do we ever specifically recommend an upgrade from check?

Also it might be better off to have the first full paragraph be a more
general explanation like this:

  Upgrading to a newer format may improve performance or make
  new features available, but it may limit interoperability with
  older repositories or with older versions of Bazaar.

Strictly speaking you can also use upgrade to downgrade; it doesn't have
to be to a newer format.

+
+ If the location given is a shared repository, dependent branches
+ are also converted provided the repository converts successfully.
+ If the conversion of a branch fails, remaining branches are still tried.
+
+ A backup.bzr directory is created at the start of the conversion
+ process. By default, this is left there on completion. If the
+ conversion fails, delete the new .bzr directory and rename this
+ one back in its place. Use the --clean option to ask for the
+ backup.bzr directory to be removed on successful conversion.
+ Alternatively, you can delete it by hand if everything looks
+ good afterwards.
+
+ It is often a good idea to pack the repository after an upgrade.
+ Use the --pack option to request this or do it separately using
+ the pack command.
+
+ For more information on upgrades, see the Bazaar 2.0 Upgrade Guide.
     """

- _see_also = ['check']
+ _see_also = ['check', 'reconcile', 'pack']

Also current-formats etc?

     takes_args = ['url?']
     takes_options = [
- RegistryOption('format',
- help='Upgrade to a specific format. See "bzr help'
- ...

review: Needs Information
Revision history for this message
Martin Pool (mbp) wrote :

I think this is now back in Ian's court.

Revision history for this message
Matthew Fuller (fullermd) wrote :

See mp42746 for an updated version of this.

Revision history for this message
Vincent Ladeuil (vila) wrote :

This could be considered merged now.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2009-08-30 23:51:10 +0000
+++ NEWS 2009-08-31 04:36:58 +0000
@@ -9,6 +9,7 @@
9In Development9In Development
10##############10##############
1111
12<<<<<<< TREE
12Compatibility Breaks13Compatibility Breaks
13********************14********************
1415
@@ -90,6 +91,8 @@
90least six months or until the following stable release (we said91least six months or until the following stable release (we said
91that previously, but that's worth repeating).92that previously, but that's worth repeating).
9293
94=======
95>>>>>>> MERGE-SOURCE
93Compatibility Breaks96Compatibility Breaks
94********************97********************
9598
@@ -107,12 +110,25 @@
107New Features110New Features
108************111************
109112
113<<<<<<< TREE
110* ``bzr branch --switch`` can now switch the checkout in the current directory114* ``bzr branch --switch`` can now switch the checkout in the current directory
111 to the newly created branch. (Lukáš Lalinský)115 to the newly created branch. (Lukáš Lalinský)
112116
117=======
118* ``upgrade`` now upgrades dependent branches when a shared repository is
119 specified. It also supports several new options:
120
121 * ``--dry-run`` for showing what will happen
122
123 * ``--clean`` to remove the backup.dir directory on successful completion.
124
125 (Ian Clatworthy)
126
127>>>>>>> MERGE-SOURCE
113Bug Fixes128Bug Fixes
114*********129*********
115130
131<<<<<<< TREE
116* Further tweaks to handling of ``bzr add`` messages about ignored files.132* Further tweaks to handling of ``bzr add`` messages about ignored files.
117 (Jason Spashett, #76616)133 (Jason Spashett, #76616)
118134
@@ -141,6 +157,11 @@
141 fetching only a few hundred bytes at a time.157 fetching only a few hundred bytes at a time.
142 (Andrew Bennetts, #402657)158 (Andrew Bennetts, #402657)
143159
160=======
161* Fix a test failure on karmic by making a locale test more robust.
162 (Vincent Ladeuil, #413514)
163
164>>>>>>> MERGE-SOURCE
144Improvements165Improvements
145************166************
146167
@@ -379,6 +400,7 @@
379 if password authentication is even supported. This fixes a bug where400 if password authentication is even supported. This fixes a bug where
380 users would be prompted for a launchpad password, even though launchpad401 users would be prompted for a launchpad password, even though launchpad
381 only supports publickey authentication. (John Arbash Meinel, #375867)402 only supports publickey authentication. (John Arbash Meinel, #375867)
403>>>>>>> MERGE-SOURCE
382404
383* BranchBuilder now accepts timezone to avoid test failures in countries far405* BranchBuilder now accepts timezone to avoid test failures in countries far
384 from GMT. (Vincent Ladeuil, #397716)406 from GMT. (Vincent Ladeuil, #397716)
385407
=== modified file 'bzrlib/builtins.py'
--- bzrlib/builtins.py 2009-08-28 05:00:33 +0000
+++ bzrlib/builtins.py 2009-08-31 04:36:59 +0000
@@ -3139,27 +3139,62 @@
31393139
31403140
3141class cmd_upgrade(Command):3141class cmd_upgrade(Command):
3142 """Upgrade branch storage to current format.3142 """Upgrade a repository, branch or working tree to a newer format.
31433143
3144 The check command or bzr developers may sometimes advise you to run3144 When the default format has changed after a major new release of
3145 this command. When the default format has changed you may also be warned3145 Bazaar, you may be informed during certain operations that you
3146 during other operations to upgrade.3146 should upgrade. Upgrading to a newer format may improve performance
3147 or make new features available. It may however limit interoperability
3148 with older repositories or with older versions of Bazaar.
3149
3150 If you wish to upgrade to a particular format rather than the
3151 current default, that can be specified using the --format option.
3152 As a consequence, you can use the upgrade command this way to
3153 "downgrade" to an earlier format, though some conversions are
3154 a one way process (e.g. changing from the 1.x default to the
3155 2.x default) so downgrading is not always possible.
3156
3157 A backup.bzr directory is created at the start of the conversion
3158 process. By default, this is left there on completion. If the
3159 conversion fails, delete the new .bzr directory and rename this
3160 one back in its place. Use the --clean option to ask for the
3161 backup.bzr directory to be removed on successful conversion.
3162 Alternatively, you can delete it by hand if everything looks
3163 good afterwards.
3164
3165 If the location given is a shared repository, dependent branches
3166 are also converted provided the repository converts successfully.
3167 If the conversion of a branch fails, remaining branches are still
3168 tried.
3169
3170 For more information on upgrades, see the Bazaar 2.0 Upgrade Guide,
3171 http://doc.bazaar-vcs.org/latest/en/upgrade-guide/.
3147 """3172 """
31483173
3149 _see_also = ['check']3174 _see_also = ['check', 'reconcile', 'formats']
3150 takes_args = ['url?']3175 takes_args = ['url?']
3151 takes_options = [3176 takes_options = [
3152 RegistryOption('format',3177 RegistryOption('format',
3153 help='Upgrade to a specific format. See "bzr help'3178 help='Upgrade to a specific format. See "bzr help'
3154 ' formats" for details.',3179 ' formats" for details.',
3155 lazy_registry=('bzrlib.bzrdir', 'format_registry'),3180 lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3156 converter=lambda name: bzrdir.format_registry.make_bzrdir(name),3181 converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3157 value_switches=True, title='Branch format'),3182 value_switches=True, title='Branch format'),
3158 ]3183 Option('clean',
3184 help='Remove the backup.bzr directory if successful.'),
3185 Option('dry-run',
3186 help="Show what would be done, but don't actually do anything."),
3187 ]
31593188
3160 def run(self, url='.', format=None):3189 def run(self, url='.', format=None, clean=False, dry_run=False):
3161 from bzrlib.upgrade import upgrade3190 from bzrlib.upgrade import upgrade
3162 upgrade(url, format)3191 exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3192 if exceptions:
3193 if len(exceptions) == 1:
3194 # This provides backwards compatibility
3195 raise exceptions[0]
3196 else:
3197 return 3
31633198
31643199
3165class cmd_whoami(Command):3200class cmd_whoami(Command):
31663201
=== modified file 'bzrlib/bzrdir.py'
--- bzrlib/bzrdir.py 2009-08-21 02:10:06 +0000
+++ bzrlib/bzrdir.py 2009-08-31 04:36:59 +0000
@@ -88,7 +88,7 @@
8888
8989
90class BzrDir(object):90class BzrDir(object):
91 """A .bzr control diretory.91 """A .bzr control directory.
9292
93 BzrDir instances let you create or open any of the things that can be93 BzrDir instances let you create or open any of the things that can be
94 found within .bzr - checkouts, branches and repositories.94 found within .bzr - checkouts, branches and repositories.
@@ -1300,6 +1300,40 @@
1300 push_result.branch_push_result.target_branch1300 push_result.branch_push_result.target_branch
1301 return push_result1301 return push_result
13021302
1303 def _get_object_and_label(self):
1304 """Return the primary object and type label for a control directory.
1305
1306 :return: object, label where
1307 object is a Branch, Repository or WorkingTree and
1308 label is one of:
1309 branch - a branch
1310 repository - a repository
1311 tree - a lightweight checkout
1312 """
1313 try:
1314 try:
1315 br = self.open_branch(unsupported=True, ignore_fallbacks=True)
1316 except TypeError:
1317 # RemoteRepository doesn't support the unsupported parameter
1318 br = self.open_branch(ignore_fallbacks=True)
1319 except errors.NotBranchError:
1320 pass
1321 else:
1322 return br, "branch"
1323 try:
1324 repo = self.open_repository()
1325 except errors.NoRepositoryPresent:
1326 pass
1327 else:
1328 return repo, "repository"
1329 try:
1330 wt = self.open_workingtree()
1331 except (errors.NoWorkingTree, errors.NotLocalUrl):
1332 pass
1333 else:
1334 return wt, "tree"
1335 raise AssertionError("unknown type of control directory %s", self)
1336
13031337
1304class BzrDirHooks(hooks.Hooks):1338class BzrDirHooks(hooks.Hooks):
1305 """Hooks for BzrDir operations."""1339 """Hooks for BzrDir operations."""
13061340
=== modified file 'bzrlib/tests/blackbox/test_upgrade.py'
--- bzrlib/tests/blackbox/test_upgrade.py 2009-08-21 02:10:06 +0000
+++ bzrlib/tests/blackbox/test_upgrade.py 2009-08-31 04:36:59 +0000
@@ -154,6 +154,29 @@
154 self.run_bzr('init-repository --format=metaweave repo')154 self.run_bzr('init-repository --format=metaweave repo')
155 self.run_bzr('upgrade --format=knit repo')155 self.run_bzr('upgrade --format=knit repo')
156156
157 def _assert_option_legal(self, option_str):
158 # Confirm that an option is legal. (Lower level tests are
159 # expected to validate the actual functionality.)
160 self.run_bzr('init --format=pack-0.92 branch-foo')
161 self.run_bzr('upgrade --format=2a branch-foo %s' % (option_str,))
162
163 def _assert_branch_format(self, dir, format):
164 branch = bzrdir.BzrDir.open_tree_or_branch(self.get_url(dir))[1]
165 branch_format = branch._format
166 meta_format = bzrdir.format_registry.make_bzrdir(format)
167 expected_format = meta_format.get_branch_format()
168 self.assertEqual(expected_format, branch_format)
169
170 def test_upgrade_clean_supported(self):
171 self._assert_option_legal('--clean')
172 self._assert_branch_format('branch-foo', '2a')
173 backup_bzr_dir = os.path.join("branch-foo", "backup.bzr")
174 self.assertFalse(os.path.exists(backup_bzr_dir))
175
176 def test_upgrade_dry_run_supported(self):
177 self._assert_option_legal('--dry-run')
178 self._assert_branch_format('branch-foo', 'pack-0.92')
179
157180
158class SFTPTests(TestCaseWithSFTPServer):181class SFTPTests(TestCaseWithSFTPServer):
159 """Tests for upgrade over sftp."""182 """Tests for upgrade over sftp."""
160183
=== modified file 'bzrlib/tests/test_foreign.py'
--- bzrlib/tests/test_foreign.py 2009-08-17 07:54:34 +0000
+++ bzrlib/tests/test_foreign.py 2009-08-31 04:36:59 +0000
@@ -249,7 +249,7 @@
249 self._control_files = lockable_files.LockableFiles(self.transport,249 self._control_files = lockable_files.LockableFiles(self.transport,
250 "lock", lockable_files.TransportLock)250 "lock", lockable_files.TransportLock)
251251
252 def open_branch(self, ignore_fallbacks=True):252 def open_branch(self, unsupported=False, ignore_fallbacks=True):
253 return self._format.get_branch_format().open(self, _found=True)253 return self._format.get_branch_format().open(self, _found=True)
254254
255 def cloning_metadir(self, stacked=False):255 def cloning_metadir(self, stacked=False):
256256
=== modified file 'bzrlib/tests/test_upgrade.py'
--- bzrlib/tests/test_upgrade.py 2009-05-07 05:08:46 +0000
+++ bzrlib/tests/test_upgrade.py 2009-08-31 04:36:59 +0000
@@ -29,6 +29,7 @@
29from bzrlib import (29from bzrlib import (
30 branch as _mod_branch,30 branch as _mod_branch,
31 bzrdir,31 bzrdir,
32 osutils,
32 progress,33 progress,
33 repository,34 repository,
34 workingtree,35 workingtree,
@@ -38,7 +39,7 @@
38from bzrlib.branch import Branch39from bzrlib.branch import Branch
39from bzrlib.tests import TestCaseWithTransport40from bzrlib.tests import TestCaseWithTransport
40from bzrlib.transport import get_transport41from bzrlib.transport import get_transport
41from bzrlib.upgrade import upgrade42from bzrlib.upgrade import upgrade, smart_upgrade
4243
4344
44class TestUpgrade(TestCaseWithTransport):45class TestUpgrade(TestCaseWithTransport):
@@ -428,3 +429,62 @@
428 ),429 ),
429 ( './dir/', ),430 ( './dir/', ),
430]431]
432
433
434class TestSmartUpgrade(TestCaseWithTransport):
435
436 from_format = "pack-0.92"
437 to_format = bzrdir.format_registry.make_bzrdir("2a")
438
439 def make_standalone_branch(self):
440 wt = self.make_branch_and_tree("branch1", format=self.from_format)
441 return wt.bzrdir
442
443 def test_upgrade_standalone_branch(self):
444 control = self.make_standalone_branch()
445 tried, worked, issues = smart_upgrade([control], format=self.to_format)
446 self.assertEqual(1, len(tried))
447 self.assertEqual(1, len(worked))
448 self.assertEqual(0, len(issues))
449 self.failUnlessExists('branch1/backup.bzr')
450
451 def test_upgrade_standalone_branch_cleanup(self):
452 control = self.make_standalone_branch()
453 tried, worked, issues = smart_upgrade([control], format=self.to_format,
454 clean_up=True)
455 self.assertEqual(1, len(tried))
456 self.assertEqual(1, len(worked))
457 self.assertEqual(0, len(issues))
458 self.failUnlessExists('branch1')
459 self.failUnlessExists('branch1/.bzr')
460 self.failIfExists('branch1/backup.bzr')
461
462 def make_repo_with_branches(self):
463 repo = self.make_repository('repo', shared=True,
464 format=self.from_format)
465 b1 = self.make_branch("repo/branch1", format=self.from_format)
466 b2 = self.make_branch("repo/branch2", format=self.from_format)
467 return repo.bzrdir
468
469 def test_upgrade_repo_with_branches(self):
470 control = self.make_repo_with_branches()
471 tried, worked, issues = smart_upgrade([control], format=self.to_format)
472 self.assertEqual(3, len(tried))
473 self.assertEqual(3, len(worked))
474 self.assertEqual(0, len(issues))
475 self.failUnlessExists('repo/backup.bzr')
476 self.failUnlessExists('repo/branch1/backup.bzr')
477 self.failUnlessExists('repo/branch2/backup.bzr')
478
479 def test_upgrade_repo_with_branches_cleanup(self):
480 control = self.make_repo_with_branches()
481 tried, worked, issues = smart_upgrade([control], format=self.to_format,
482 clean_up=True)
483 self.assertEqual(3, len(tried))
484 self.assertEqual(3, len(worked))
485 self.assertEqual(0, len(issues))
486 self.failUnlessExists('repo')
487 self.failUnlessExists('repo/.bzr')
488 self.failIfExists('repo/backup.bzr')
489 self.failIfExists('repo/branch1/backup.bzr')
490 self.failIfExists('repo/branch2/backup.bzr')
431491
=== modified file 'bzrlib/upgrade.py'
--- bzrlib/upgrade.py 2009-05-07 05:08:46 +0000
+++ bzrlib/upgrade.py 2009-08-31 04:36:59 +0000
@@ -17,18 +17,36 @@
17"""bzr upgrade logic."""17"""bzr upgrade logic."""
1818
1919
20from bzrlib import osutils, repository
20from bzrlib.bzrdir import BzrDir, BzrDirFormat, format_registry21from bzrlib.bzrdir import BzrDir, BzrDirFormat, format_registry
21import bzrlib.errors as errors22import bzrlib.errors as errors
22from bzrlib.remote import RemoteBzrDir23from bzrlib.remote import RemoteBzrDir
23from bzrlib.transport import get_transport24from bzrlib.transport import get_transport
25from bzrlib.trace import mutter, note, warning
24import bzrlib.ui as ui26import bzrlib.ui as ui
2527
2628
27class Convert(object):29class Convert(object):
2830
29 def __init__(self, url, format=None):31 def __init__(self, url=None, format=None, control_dir=None):
32 """Convert a Bazaar control directory to a given format.
33
34 Either the url or control_dir parameter must be given.
35
36 :param url: the URL of the control directory or None if the
37 control_dir is explicitly given instead
38 :param format: the format to convert to or None for the default
39 :param control_dir: the control directory or None if it is
40 specified via the URL parameter instead
41 """
30 self.format = format42 self.format = format
31 self.bzrdir = BzrDir.open_unsupported(url)43 if url is None and control_dir is None:
44 raise AssertionError(
45 "either the url or control_dir parameter must be set.")
46 if control_dir is not None:
47 self.bzrdir = control_dir
48 else:
49 self.bzrdir = BzrDir.open_unsupported(url)
32 if isinstance(self.bzrdir, RemoteBzrDir):50 if isinstance(self.bzrdir, RemoteBzrDir):
33 self.bzrdir._ensure_real()51 self.bzrdir._ensure_real()
34 self.bzrdir = self.bzrdir._real_bzrdir52 self.bzrdir = self.bzrdir._real_bzrdir
@@ -73,13 +91,179 @@
73 self.bzrdir._format)91 self.bzrdir._format)
74 self.bzrdir.check_conversion_target(format)92 self.bzrdir.check_conversion_target(format)
75 self.pb.note('starting upgrade of %s', self.transport.base)93 self.pb.note('starting upgrade of %s', self.transport.base)
76 self.bzrdir.backup_bzrdir()94 self.backup_oldpath, self.backup_newpath = self.bzrdir.backup_bzrdir()
77 while self.bzrdir.needs_format_conversion(format):95 while self.bzrdir.needs_format_conversion(format):
78 converter = self.bzrdir._format.get_converter(format)96 converter = self.bzrdir._format.get_converter(format)
79 self.bzrdir = converter.convert(self.bzrdir, self.pb)97 self.bzrdir = converter.convert(self.bzrdir, self.pb)
80 self.pb.note("finished")98 self.pb.note("finished")
8199
82100 def clean_up(self):
83def upgrade(url, format=None):101 """Clean-up after a conversion.
84 """Upgrade to format, or the default bzrdir format if not supplied."""102
85 Convert(url, format)103 This removes the backup.bzr directory.
104 """
105 transport = self.transport
106 backup_relpath = transport.relpath(self.backup_newpath)
107 transport.delete_tree(backup_relpath)
108
109
110def upgrade(urls, format=None, clean_up=False, pack=False, dry_run=False):
111 """Upgrade locations to format.
112
113 This routine wraps the smart_upgrade() routine with a nicer UI.
114 In particular, it ensures all URLs can be opened before starting
115 and reports a summary at the end if more than one upgrade was attempted.
116 This routine is useful for command line tools. Other bzrlib clients
117 probably ought to use smart_upgrade() instead.
118
119 :param urls: a sequence of URLs to the locations to upgrade.
120 For backwards compatibility, if urls is a string, it is treated
121 as a single URL.
122 :param format: the format to convert to or None for the best default
123 :param clean-up: if True, the backup.bzr directory is removed if the
124 upgrade succeeded for a given repo/branch/tree
125 :param pack: pack repositories that successfully upgrade
126 :param dry_run: show what would happen but don't actually do any upgrades
127 :return: the list of exceptions encountered
128 """
129 if isinstance(urls, basestring):
130 urls = [urls]
131 control_dirs = [BzrDir.open_unsupported(url) for url in urls]
132 attempted, succeeded, exceptions = smart_upgrade(control_dirs,
133 format, clean_up=clean_up, pack=pack, dry_run=dry_run)
134 if len(attempted) > 1:
135 attempted_count = len(attempted)
136 succeeded_count = len(succeeded)
137 failed_count = attempted_count - succeeded_count
138 note("\nSUMMARY: %d upgrades attempted, %d succeeded, %d failed",
139 attempted_count, succeeded_count, failed_count)
140 return exceptions
141
142
143def smart_upgrade(control_dirs, format, clean_up=False, pack=False,
144 dry_run=False):
145 """Convert control directories to a new format intelligently.
146
147 If the control directory is a shared repository, dependent branches
148 are also converted provided the repository converted successfully.
149 If the conversion of a branch fails, remaining branches are still tried.
150
151 :param control_dirs: the BzrDirs to upgrade
152 :param format: the format to convert to or None for the best default
153 :param clean-up: if True, the backup.bzr directory is removed if the
154 upgrade succeeded for a given repo/branch/tree
155 :param pack: pack repositories that successfully upgrade
156 :param dry_run: show what would happen but don't actually do any upgrades
157 :return: attempted-control-dirs, succeeded-control-dirs, exceptions
158 """
159 all_attempted = []
160 all_succeeded = []
161 all_exceptions = []
162 for control_dir in control_dirs:
163 attempted, succeeded, exceptions = _smart_upgrade_one(control_dir,
164 format, clean_up=clean_up, pack=pack, dry_run=dry_run)
165 all_attempted.extend(attempted)
166 all_succeeded.extend(succeeded)
167 all_exceptions.extend(exceptions)
168 return all_attempted, all_succeeded, all_exceptions
169
170
171def _smart_upgrade_one(control_dir, format, clean_up=False, pack=False,
172 dry_run=False):
173 """Convert a control directory to a new format intelligently.
174
175 See smart_upgrade for parameter details.
176 """
177 # If the URL is a shared repository, find the dependent branches
178 dependents = None
179 try:
180 repo = control_dir.open_repository()
181 except errors.NoRepositoryPresent:
182 # A branch or checkout using a shared repository higher up
183 pass
184 else:
185 # The URL is a repository. If it successfully upgrades,
186 # then upgrade the dependent branches as well.
187 if repo.is_shared():
188 dependents = repo.find_branches(using=True)
189
190 # Do the conversions
191 attempted = [control_dir]
192 succeeded, exceptions = _convert_items([control_dir], format, clean_up,
193 pack, dry_run, verbose=dependents)
194 if succeeded and dependents:
195 note("Found %d dependent branches - upgrading ...", len(dependents))
196
197 # Convert dependent branches
198 branch_cdirs = [b.bzrdir for b in dependents]
199 successes, problems = _convert_items(branch_cdirs, format, clean_up,
200 pack, dry_run, label="branch")
201 attempted.extend(branch_cdirs)
202 succeeded.extend(successes)
203 exceptions.extend(problems)
204
205 # Return the result
206 return attempted, succeeded, exceptions
207
208
209def _convert_items(items, format, clean_up, pack, dry_run, label=None,
210 verbose=True):
211 """Convert a sequence of control directories to the given format.
212
213 :param items: the control directories to upgrade
214 :param format: the format to convert to or None for the best default
215 :param clean-up: if True, the backup.bzr directory is removed if the
216 upgrade succeeded for a given repo/branch/tree
217 :param pack: pack repositories that successfully upgrade
218 :param dry_run: show what would happen but don't actually do any upgrades
219 :param label: the label for these items or None to calculate one
220 :param verbose: if True, output a message before starting and
221 display any problems encountered
222 :return: items successfully upgraded, exceptions
223 """
224 succeeded = []
225 exceptions = []
226 for control_dir in items:
227 # Do the conversion
228 location = control_dir.root_transport.base
229 bzr_object, bzr_label = control_dir._get_object_and_label()
230 if verbose:
231 type_label = label or bzr_label
232 note("Upgrading %s %s ...", type_label, location)
233 try:
234 if not dry_run:
235 cv = Convert(control_dir=control_dir, format=format)
236 except Exception, ex:
237 _verbose_warning(verbose, "conversion error: %s" % ex)
238 exceptions.append(ex)
239 continue
240
241 # Do any required post processing
242 succeeded.append(control_dir)
243 if pack and isinstance(bzr_object, repository.Repository):
244 note("Packing ...")
245 try:
246 if not dry_run:
247 bzr_object.pack()
248 except Exception, ex:
249 _verbose_warning(verbose, "failed to pack %s: %s" %
250 (location, ex))
251 exceptions.append(ex)
252 if clean_up:
253 try:
254 note("Removing backup ...")
255 if not dry_run:
256 cv.clean_up()
257 except Exception, ex:
258 _verbose_warning(verbose, "failed to clean-up %s: %s" %
259 (location, ex))
260 exceptions.append(ex)
261
262 # Return the result
263 return succeeded, exceptions
264
265
266def _verbose_warning(verbose, msg):
267 mutter(msg)
268 if verbose:
269 warning(msg)