Merge lp:~rockstar/launchpad/branch-upgrade-out-of-place into lp:launchpad

Proposed by Paul Hummer
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~rockstar/launchpad/branch-upgrade-out-of-place
Merge into: lp:launchpad
Diff against target: 116 lines
2 files modified
lib/lp/code/model/branchjob.py (+31/-10)
lib/lp/code/model/tests/test_branchjob.py (+14/-13)
To merge this branch: bzr merge lp:~rockstar/launchpad/branch-upgrade-out-of-place
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle Approve
Paul Hummer (community) Approve
Review via email: mp+13747@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Paul Hummer (rockstar) wrote :

Hi Michael-

  So, this branch is basically a re-write of what I had yesterday, since I
wasn't using transports. Aaron showed me the way, and so this branch is a lot
cleaner. I also didn't change any tests, just made sure the old ones passed.
I did this because I thought the tests were getting too introspective into the
implementation. Basically, I had the job split up into _pre_upgrade, _upgrade,
and _post_upgrade methods, and were testing that each method did what it was
supposed to. This led to madness, IMHO. If you think I'm wrong, I'd be more
than happy to change it back.

  I also fixed some lint that came up in the lint report. The lint warnings
about not finding lazr are craziness.

  To test: bin/test -vvc lp.code.model.tests.test_branchjob TestBranchUpgradeJob

  I've never really had to dive this far into the bzrlib stuff before, so I
expect there are probably better ways to do what I'm doing. I'm all ears.

 reviewer mwhudson

Cheers,
Paul

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :
Download full text (5.8 KiB)

Hi Paul,

I hope you're enjoying using the bzrlib apis :-)

A few fixes required I think, nothing fundamental though.

> === modified file 'lib/lp/code/model/branchjob.py'
> --- lib/lp/code/model/branchjob.py 2009-10-20 06:03:46 +0000
> +++ lib/lp/code/model/branchjob.py 2009-10-22 00:05:29 +0000
> @@ -11,12 +11,15 @@
> import os
> import shutil
> from StringIO import StringIO
> +import tempfile
>
> +from bzrlib.branch import Branch as BzrBranch
> from bzrlib.bzrdir import BzrDirMetaFormat1
> from bzrlib.log import log_formatter, show_log
> from bzrlib.diff import show_diff_trees
> from bzrlib.revision import NULL_REVISION
> from bzrlib.revisionspec import RevisionInfo, RevisionSpec
> +from bzrlib.transport import get_transport
> from bzrlib.upgrade import upgrade
>
> from lazr.enum import DBEnumeratedType, DBItem
> @@ -252,16 +255,30 @@
>
> def run(self):
> """See `IBranchUpgradeJob`."""
> - self._prepare_upgrade()
> - self._upgrade()
> -
> - def _prepare_upgrade(self):
> - """Prepares the branch for upgrade."""
> - self._upgrade_branch = self.branch.getBzrBranch()
> -
> - def _upgrade(self):
> - """Performs the upgrade of the branch."""
> - upgrade(self._upgrade_branch.base, self.upgrade_format)
> + # Set up the new branch structure
> + upgrade_branch_path = tempfile.mkdtemp()

Everything in this method after this point should be in a try:finally:
that blows away this directory.

> + upgrade_transport = get_transport(upgrade_branch_path)
> + source_branch = self.branch.getBzrBranch()

There's a problem here, which is that getBzrBranch opens the branch in
the mirrored area, not the hosted area.

> + source_branch_transport = source_branch.bzrdir.root_transport

I think

        source_branch_transport = get_transport(self.branch.getPullURL())

is what you want; it gets a transport to the hosted area of the
branch, and is less effort than opening the branch just to get the
transport out of it. Once the copy in the hosted area is upgraded,
the puller will take care of propagating the new format into the
mirrored area.

(The names of the methods/properties are completely ridiculous, no
argument about that).

> + source_branch_transport.copy_tree_to_transport(upgrade_transport)
> + upgrade_branch = BzrBranch.open(upgrade_transport.base)
> +
> + # Perform the upgrade.
> + upgrade(upgrade_branch.base, self.upgrade_format)
> +
> + # Re-open the branch, since its format has changed.
> + upgrade_branch = BzrBranch.open(upgrade_transport.base)
> + upgrade_branch.pull(source_branch)
> + upgrade_branch.fetch(source_branch)
> +
> + # Move the branch in the old format to backup.bzr

I think you should try to write lock the branch before doing this move
to prevent confusion if someone is pushing to the branch right at this
moment.

> + source_branch_transport.rename('.bzr', 'backup.bzr')

b = Branch.open_from_transport(source_branch_transport)
b.lock_write()

I don't know what will happen when bzr notices that the underlying
branch has gone away from this lock though -- something t...

Read more...

review: Approve
Revision history for this message
Michael Hudson-Doyle (mwhudson) :
review: Needs Fixing
Revision history for this message
Paul Hummer (rockstar) wrote :
Download full text (9.1 KiB)

> > === modified file 'lib/lp/code/model/branchjob.py'
> > --- lib/lp/code/model/branchjob.py 2009-10-20 06:03:46 +0000
> > +++ lib/lp/code/model/branchjob.py 2009-10-22 00:05:29 +0000
> > @@ -11,12 +11,15 @@
> > import os
> > import shutil
> > from StringIO import StringIO
> > +import tempfile
> >
> > +from bzrlib.branch import Branch as BzrBranch
> > from bzrlib.bzrdir import BzrDirMetaFormat1
> > from bzrlib.log import log_formatter, show_log
> > from bzrlib.diff import show_diff_trees
> > from bzrlib.revision import NULL_REVISION
> > from bzrlib.revisionspec import RevisionInfo, RevisionSpec
> > +from bzrlib.transport import get_transport
> > from bzrlib.upgrade import upgrade
> >
> > from lazr.enum import DBEnumeratedType, DBItem
> > @@ -252,16 +255,30 @@
> >
> > def run(self):
> > """See `IBranchUpgradeJob`."""
> > - self._prepare_upgrade()
> > - self._upgrade()
> > -
> > - def _prepare_upgrade(self):
> > - """Prepares the branch for upgrade."""
> > - self._upgrade_branch = self.branch.getBzrBranch()
> > -
> > - def _upgrade(self):
> > - """Performs the upgrade of the branch."""
> > - upgrade(self._upgrade_branch.base, self.upgrade_format)
> > + # Set up the new branch structure
> > + upgrade_branch_path = tempfile.mkdtemp()
>
> Everything in this method after this point should be in a try:finally:
> that blows away this directory.

Done.

>
> > + upgrade_transport = get_transport(upgrade_branch_path)
> > + source_branch = self.branch.getBzrBranch()
>
> There's a problem here, which is that getBzrBranch opens the branch in
> the mirrored area, not the hosted area.
>

Yea, fixed this.

> > + source_branch_transport = source_branch.bzrdir.root_transport
>
> I think
>
> source_branch_transport = get_transport(self.branch.getPullURL())
>
> is what you want; it gets a transport to the hosted area of the
> branch, and is less effort than opening the branch just to get the
> transport out of it. Once the copy in the hosted area is upgraded,
> the puller will take care of propagating the new format into the
> mirrored area.
>
> (The names of the methods/properties are completely ridiculous, no
> argument about that).
>

Well, I still need the source_branch to pull from later, but I can get that with Branch.open_from_transport

> > + source_branch_transport.copy_tree_to_transport(upgrade_transport)
> > + upgrade_branch = BzrBranch.open(upgrade_transport.base)
> > +
> > + # Perform the upgrade.
> > + upgrade(upgrade_branch.base, self.upgrade_format)
> > +
> > + # Re-open the branch, since its format has changed.
> > + upgrade_branch = BzrBranch.open(upgrade_transport.base)
> > + upgrade_branch.pull(source_branch)
> > + upgrade_branch.fetch(source_branch)
> > +
> > + # Move the branch in the old format to backup.bzr
>
> I think you should try to write lock the branch before doing this move
> to prevent confusion if someone is pushing to the branch right at this
> moment.
>
> > + source_branch_transport.rename('.bzr', 'backup.bzr')
>
> b = Branch.o...

Read more...

review: Approve
Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

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

 merge approve

All but fine now...

Paul Hummer wrote:

> === modified file 'lib/lp/code/model/branchjob.py'
> --- lib/lp/code/model/branchjob.py 2009-10-21 23:34:08 +0000
> +++ lib/lp/code/model/branchjob.py 2009-10-22 04:22:18 +0000
> @@ -257,28 +257,32 @@
> """See `IBranchUpgradeJob`."""
> # Set up the new branch structure
> upgrade_branch_path = tempfile.mkdtemp()
> - upgrade_transport = get_transport(upgrade_branch_path)
> - source_branch = self.branch.getBzrBranch()
> - source_branch_transport = source_branch.bzrdir.root_transport
> - source_branch_transport.copy_tree_to_transport(upgrade_transport)
> - upgrade_branch = BzrBranch.open(upgrade_transport.base)
> -
> - # Perform the upgrade.
> - upgrade(upgrade_branch.base, self.upgrade_format)
> -
> - # Re-open the branch, since its format has changed.
> - upgrade_branch = BzrBranch.open(upgrade_transport.base)
> - upgrade_branch.pull(source_branch)
> - upgrade_branch.fetch(source_branch)
> -
> - # Move the branch in the old format to backup.bzr
> - source_branch_transport.rename('.bzr', 'backup.bzr')
> - upgrade_transport.delete_tree('backup.bzr')
> - upgrade_transport.copy_tree_to_transport(source_branch_transport)
> -
> - # Clean up the temporary directory.
> - upgrade_transport.delete_tree('.bzr')
> - os.rmdir(upgrade_branch_path)
> + try:
> + upgrade_transport = get_transport(upgrade_branch_path)
> + source_branch_transport = get_transport(self.branch.getPullURL())
> + source_branch_transport.copy_tree_to_transport(upgrade_transport)
> + upgrade_branch = BzrBranch.open(upgrade_transport.base)
> +
> + # Perform the upgrade.
> + upgrade(upgrade_branch.base, self.upgrade_format)
> +
> + # Re-open the branch, since its format has changed.
> + upgrade_branch = BzrBranch.open_from_transport(
> + upgrade_transport)
> + source_branch = BzrBranch.open_from_transport(
> + source_branch_transport)
> +
> + source_branch.lock_write()
> + upgrade_branch.pull(source_branch)
> + upgrade_branch.fetch(source_branch)
> + source_branch.unlock()
> +
> + # Move the branch in the old format to backup.bzr
> + source_branch_transport.rename('.bzr', 'backup.bzr')
> + upgrade_transport.delete_tree('backup.bzr')

You don't need this line.

> + upgrade_transport.copy_tree_to_transport(source_branch_transport)
> + finally:
> + shutil.rmtree(upgrade_branch_path)
>
> @property
> def upgrade_format(self):

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

iEYEARECAAYFAkrf4tAACgkQeTTOPm7A7kjE3gCfcqpSHwpQHkYyUFe6nBycGfSb
gdAAoILC14HcnXFuSv0kbBRrhRDD9StK
=zuVZ
-----END PGP SIGNATURE-----

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/model/branchjob.py'
--- lib/lp/code/model/branchjob.py 2009-10-20 06:03:46 +0000
+++ lib/lp/code/model/branchjob.py 2009-10-22 04:39:17 +0000
@@ -11,12 +11,15 @@
11import os11import os
12import shutil12import shutil
13from StringIO import StringIO13from StringIO import StringIO
14import tempfile
1415
16from bzrlib.branch import Branch as BzrBranch
15from bzrlib.bzrdir import BzrDirMetaFormat117from bzrlib.bzrdir import BzrDirMetaFormat1
16from bzrlib.log import log_formatter, show_log18from bzrlib.log import log_formatter, show_log
17from bzrlib.diff import show_diff_trees19from bzrlib.diff import show_diff_trees
18from bzrlib.revision import NULL_REVISION20from bzrlib.revision import NULL_REVISION
19from bzrlib.revisionspec import RevisionInfo, RevisionSpec21from bzrlib.revisionspec import RevisionInfo, RevisionSpec
22from bzrlib.transport import get_transport
20from bzrlib.upgrade import upgrade23from bzrlib.upgrade import upgrade
2124
22from lazr.enum import DBEnumeratedType, DBItem25from lazr.enum import DBEnumeratedType, DBItem
@@ -252,16 +255,34 @@
252255
253 def run(self):256 def run(self):
254 """See `IBranchUpgradeJob`."""257 """See `IBranchUpgradeJob`."""
255 self._prepare_upgrade()258 # Set up the new branch structure
256 self._upgrade()259 upgrade_branch_path = tempfile.mkdtemp()
257260 try:
258 def _prepare_upgrade(self):261 upgrade_transport = get_transport(upgrade_branch_path)
259 """Prepares the branch for upgrade."""262 source_branch_transport = get_transport(self.branch.getPullURL())
260 self._upgrade_branch = self.branch.getBzrBranch()263 source_branch_transport.copy_tree_to_transport(upgrade_transport)
261264 upgrade_branch = BzrBranch.open(upgrade_transport.base)
262 def _upgrade(self):265
263 """Performs the upgrade of the branch."""266 # Perform the upgrade.
264 upgrade(self._upgrade_branch.base, self.upgrade_format)267 upgrade(upgrade_branch.base, self.upgrade_format)
268
269 # Re-open the branch, since its format has changed.
270 upgrade_branch = BzrBranch.open_from_transport(
271 upgrade_transport)
272 source_branch = BzrBranch.open_from_transport(
273 source_branch_transport)
274
275 source_branch.lock_write()
276 upgrade_branch.pull(source_branch)
277 upgrade_branch.fetch(source_branch)
278 source_branch.unlock()
279
280 # Move the branch in the old format to backup.bzr
281 source_branch_transport.rename('.bzr', 'backup.bzr')
282 upgrade_transport.delete_tree('backup.bzr')
283 upgrade_transport.copy_tree_to_transport(source_branch_transport)
284 finally:
285 shutil.rmtree(upgrade_branch_path)
265286
266 @property287 @property
267 def upgrade_format(self):288 def upgrade_format(self):
268289
=== modified file 'lib/lp/code/model/tests/test_branchjob.py'
--- lib/lp/code/model/tests/test_branchjob.py 2009-10-05 14:18:33 +0000
+++ lib/lp/code/model/tests/test_branchjob.py 2009-10-22 04:39:17 +0000
@@ -183,6 +183,18 @@
183183
184 layer = LaunchpadZopelessLayer184 layer = LaunchpadZopelessLayer
185185
186 def make_format(self, branch_format=None, repo_format=None):
187 # Return a Bzr MetaDir format with the provided branch and repository
188 # formats.
189 if branch_format is None:
190 branch_format = BzrBranchFormat7
191 if repo_format is None:
192 repo_format = RepositoryFormatKnitPack6
193 format = BzrDirMetaFormat1()
194 format.set_branch_format(branch_format())
195 format._set_repository_format(repo_format())
196 return format
197
186 def test_providesInterface(self):198 def test_providesInterface(self):
187 """Ensure that BranchUpgradeJob implements IBranchUpgradeJob."""199 """Ensure that BranchUpgradeJob implements IBranchUpgradeJob."""
188 branch = self.factory.makeAnyBranch()200 branch = self.factory.makeAnyBranch()
@@ -192,7 +204,8 @@
192 def test_upgrades_branch(self):204 def test_upgrades_branch(self):
193 """Ensure that a branch with an outdated format is upgraded."""205 """Ensure that a branch with an outdated format is upgraded."""
194 self.useBzrBranches()206 self.useBzrBranches()
195 db_branch, tree = self.create_branch_and_tree(format='knit')207 db_branch, tree = self.create_branch_and_tree(
208 hosted=True, format='knit')
196 db_branch.branch_format = BranchFormat.BZR_BRANCH_5209 db_branch.branch_format = BranchFormat.BZR_BRANCH_5
197 db_branch.repository_format = RepositoryFormat.BZR_KNIT_1210 db_branch.repository_format = RepositoryFormat.BZR_KNIT_1
198 self.assertEqual(211 self.assertEqual(
@@ -224,18 +237,6 @@
224 REPOSITORY_FORMAT_UPGRADE_PATH.get(237 REPOSITORY_FORMAT_UPGRADE_PATH.get(
225 RepositoryFormat.BZR_REPOSITORY_4))238 RepositoryFormat.BZR_REPOSITORY_4))
226239
227 def make_format(self, branch_format=None, repo_format=None):
228 # Return a Bzr MetaDir format with the provided branch and repository
229 # formats.
230 if branch_format is None:
231 branch_format = BzrBranchFormat7
232 if repo_format is None:
233 repo_format = RepositoryFormatKnitPack6
234 format = BzrDirMetaFormat1()
235 format.set_branch_format(branch_format())
236 format._set_repository_format(repo_format())
237 return format
238
239 def test_upgrade_format_no_branch_upgrade_needed(self):240 def test_upgrade_format_no_branch_upgrade_needed(self):
240 # getUpgradeFormat should not downgrade the branch format when it is241 # getUpgradeFormat should not downgrade the branch format when it is
241 # more up to date than the default formats provided.242 # more up to date than the default formats provided.