Merge lp:~jameinel/bzr/1.16-remote-format-stacking into lp:~bzr/bzr/trunk-old

Proposed by John A Meinel
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jameinel/bzr/1.16-remote-format-stacking
Merge into: lp:~bzr/bzr/trunk-old
Diff against target: 218 lines
To merge this branch: bzr merge lp:~jameinel/bzr/1.16-remote-format-stacking
Reviewer Review Type Date Requested Status
Andrew Bennetts Approve
Robert Collins (community) Approve
Review via email: mp+7042@code.launchpad.net
To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

This should fix some of the remaining issues with stacking and non-default formats.

This isn't a 'perfect' fix, as on the server it will still give warnings like:
Source branch format does not support stacking, using format:
  Branch format 7

That is because it still is trying to upgrade the 'default format branch' because it doesn't support stacking, even though 'initialize_on_transport_ex' *isn't* trying to create a branch anyway.

However, stacking *works* now, rather than failing because the repository format is accidentally downgraded because the default branch format doesn't support stacking...

It also has that doing 'bzr branch dev6/format_6_branch --stacked test' also now still works, since it only upgrades the branch format to format 7, and doesn't try to downgrade the repository format.

It has the advantage that 'acquire_repository()' doesn't try to hard-code its own set of formats, the formats are only encoded in BzrDirFormat1.require_stacking. Though this means that we now auto-upgrade to 1.6 rather than the 1.9 that was hard-coded in acquire_repository. (I figured better to be consistent with the older code.)

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

 review approve

review: Approve
Revision history for this message
Andrew Bennetts (spiv) wrote :

 review approve

Basically good, but I have some comments:

John A Meinel wrote:
[...]
> === modified file 'bzrlib/bzrdir.py'
> --- bzrlib/bzrdir.py 2009-06-03 04:42:02 +0000
> +++ bzrlib/bzrdir.py 2009-06-03 20:03:55 +0000
> @@ -2358,26 +2358,95 @@
> def set_branch_format(self, format):
> self._branch_format = format
>
> - def require_stacking(self):
> + def require_stacking(self, stack_on=None, possible_transports=[]):

Don't use [] as a default argument, as it is mutable. Do
possible_transports=None, as we do everywhere else.

(It's probably safe here, but it looks dangerous and is easy to avoid.)

[...]
> + try:
> + target_dir = BzrDir.open(stack_on,
> + possible_transports=possible_transports)
> + except errors.NotBranchError:
> + # Nothing there, don't change formats
> + target[:] = [None, True, False]
> + return target
> + except errors.JailBreak:
> + # JailBreak, JFDI and upgrade anyway
> + target[:] = [None, True, True]
> + return target
> + try:
> + target_branch = target_dir.open_branch()
> + except errors.NotBranchError:
> + # No branch, don't upgrade formats
> + target[:] = [None, True, False]
> + return target
> + target[:] = [target_branch, True, False]
> + return target

I wonder what happens if a repository is already present, but not a branch?
Or if target_dir is contained in a shared repo?

> + if not (self.repository_format.supports_external_lookups):
> + # We need to upgrade the Repository.
> + target_branch, _, do_upgrade = get_target_branch()
> + if target_branch is None:
> + # We don't have a target branch, should we upgrade anyway?
> + if do_upgrade:
> + # stack_on is inaccessible, JFDI.
> + # TODO: bad monkey, hard-coded formats...
> + if self.repository_format.rich_root_data:
> + new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
> + else:
> + new_repo_format = pack_repo.RepositoryFormatKnitPack5()

At least this won't accidentally downgrade the source format, I guess.
Personally I'd lean towards making 1.9 rather than 1.6 now, on the basis
that 1.9 isn't that new anymore (and relatively speaking is not much newer
than 1.6 anymore), but hopefully this isn't a big deal either way.

review: Approve
Revision history for this message
John A Meinel (jameinel) wrote :
Download full text (4.4 KiB)

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

Andrew Bennetts wrote:
> Review: Approve
> review approve

...

>> - def require_stacking(self):
>> + def require_stacking(self, stack_on=None, possible_transports=[]):
>
> Don't use [] as a default argument, as it is mutable. Do
> possible_transports=None, as we do everywhere else.
>
> (It's probably safe here, but it looks dangerous and is easy to avoid.)
>

Sure. I wasn't sure if passing None down the stack was supported, but it
seems to be fine. And yes, I know about the pitfalls of mutating default
parameters, but I'm happy to avoid it entirely.

> [...]
>> + try:
>> + target_dir = BzrDir.open(stack_on,
>> + possible_transports=possible_transports)
>> + except errors.NotBranchError:
>> + # Nothing there, don't change formats
>> + target[:] = [None, True, False]
>> + return target
>> + except errors.JailBreak:
>> + # JailBreak, JFDI and upgrade anyway
>> + target[:] = [None, True, True]
>> + return target
>> + try:
>> + target_branch = target_dir.open_branch()
>> + except errors.NotBranchError:
>> + # No branch, don't upgrade formats
>> + target[:] = [None, True, False]
>> + return target
>> + target[:] = [target_branch, True, False]
>> + return target
>
> I wonder what happens if a repository is already present, but not a branch?
> Or if target_dir is contained in a shared repo?

Interesting thought. You actually can only stack on another branch. The
code in question is:
   def _get_fallback_repository(self, url):
       """Get the repository we fallback to at url."""
       url = urlutils.join(self.base, url)
       a_bzrdir = bzrdir.BzrDir.open(url,
           possible_transports=[self.bzrdir.root_transport])
       return a_bzrdir.open_branch().repository

The trick is here ^^^^^^^^^^^^^

So if the target_dir doesn't contain a branch, stacking is going to
fail, anyway. This is mostly about people using a pack-0.92 copy of
bzr.dev, and pushing up to Launchpad when lp:bzr is in 1.9 format
anyway. It was considered "ok" to auto upgrade the public branch in that
case just at the request of Launchpad's default stacking policy. (I
think this had more fallout from Branch6 since upgrading your repo
didn't upgrade your branch format, etc.)

>
>> + if not (self.repository_format.supports_external_lookups):
>> + # We need to upgrade the Repository.
>> + target_branch, _, do_upgrade = get_target_branch()
>> + if target_branch is None:
>> + # We don't have a target branch, should we upgrade anyway?
>> + if do_upgrade:
>> + # stack_on is inaccessible, JFDI.
>> + # TODO: bad monkey, hard-coded formats...
>> + if self.repository_format.rich_root_data:
>> + new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
>> + else:
>> + new_rep...

Read more...

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

On Thu, 2009-06-04 at 02:15 +0000, John A Meinel wrote:
>
> The former is giving a very nice message to the user "using a format
> which adds stacking support". The later is very unclear "why does it
> matter that it uses btree indexes?"
>
> Also, if they are using a format that *doesn't* support stacking, then
> 1.6 is the smallest possible upgrade. (Also, note that debian stable
> only has bzr 1.5...)

Well, I don't think the message is a strong argument. And stacking
before 1.9ish worked very badly anyway, which is why I'd used 1.9. But I
don't really care which is why I was approving your patch as-was.

-Rob

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bzrlib/bzrdir.py'
2--- bzrlib/bzrdir.py 2009-06-03 04:42:02 +0000
3+++ bzrlib/bzrdir.py 2009-06-04 02:35:11 +0000
4@@ -2358,26 +2358,95 @@
5 def set_branch_format(self, format):
6 self._branch_format = format
7
8- def require_stacking(self):
9+ def require_stacking(self, stack_on=None, possible_transports=None):
10+ """We have a request to stack, try to ensure the formats support it.
11+
12+ :param stack_on: If supplied, it is the URL to a branch that we want to
13+ stack on. Check to see if that format supports stacking before
14+ forcing an upgrade.
15+ """
16+ # Stacking is desired. requested by the target, but does the place it
17+ # points at support stacking? If it doesn't then we should
18+ # not implicitly upgrade. We check this here.
19+ new_repo_format = None
20+ new_branch_format = None
21+
22+ # a bit of state for get_target_branch so that we don't try to open it
23+ # 2 times, for both repo *and* branch
24+ target = [None, False, None] # target_branch, checked, upgrade anyway
25+ def get_target_branch():
26+ if target[1]:
27+ # We've checked, don't check again
28+ return target
29+ if stack_on is None:
30+ # No target format, that means we want to force upgrading
31+ target[:] = [None, True, True]
32+ return target
33+ try:
34+ target_dir = BzrDir.open(stack_on,
35+ possible_transports=possible_transports)
36+ except errors.NotBranchError:
37+ # Nothing there, don't change formats
38+ target[:] = [None, True, False]
39+ return target
40+ except errors.JailBreak:
41+ # JailBreak, JFDI and upgrade anyway
42+ target[:] = [None, True, True]
43+ return target
44+ try:
45+ target_branch = target_dir.open_branch()
46+ except errors.NotBranchError:
47+ # No branch, don't upgrade formats
48+ target[:] = [None, True, False]
49+ return target
50+ target[:] = [target_branch, True, False]
51+ return target
52+
53+ if not (self.repository_format.supports_external_lookups):
54+ # We need to upgrade the Repository.
55+ target_branch, _, do_upgrade = get_target_branch()
56+ if target_branch is None:
57+ # We don't have a target branch, should we upgrade anyway?
58+ if do_upgrade:
59+ # stack_on is inaccessible, JFDI.
60+ # TODO: bad monkey, hard-coded formats...
61+ if self.repository_format.rich_root_data:
62+ new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
63+ else:
64+ new_repo_format = pack_repo.RepositoryFormatKnitPack5()
65+ else:
66+ # If the target already supports stacking, then we know the
67+ # project is already able to use stacking, so auto-upgrade
68+ # for them
69+ new_repo_format = target_branch.repository._format
70+ if not new_repo_format.supports_external_lookups:
71+ # target doesn't, source doesn't, so don't auto upgrade
72+ # repo
73+ new_repo_format = None
74+ if new_repo_format is not None:
75+ self.repository_format = new_repo_format
76+ note('Source repository format does not support stacking,'
77+ ' using format:\n %s',
78+ new_repo_format.get_format_description())
79+
80 if not self.get_branch_format().supports_stacking():
81- # We need to make a stacked branch, but the default format for the
82- # target doesn't support stacking. So force a branch that *can*
83- # support stacking.
84- from bzrlib.branch import BzrBranchFormat7
85- branch_format = BzrBranchFormat7()
86- self.set_branch_format(branch_format)
87- mutter("using %r for stacking" % (branch_format,))
88- from bzrlib.repofmt import pack_repo
89- if self.repository_format.rich_root_data:
90- bzrdir_format_name = '1.6.1-rich-root'
91- repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
92+ # We just checked the repo, now lets check if we need to
93+ # upgrade the branch format
94+ target_branch, _, do_upgrade = get_target_branch()
95+ if target_branch is None:
96+ if do_upgrade:
97+ # TODO: bad monkey, hard-coded formats...
98+ new_branch_format = branch.BzrBranchFormat7()
99 else:
100- bzrdir_format_name = '1.6'
101- repo_format = pack_repo.RepositoryFormatKnitPack5()
102- note('Source format does not support stacking, using format:'
103- ' \'%s\'\n %s\n',
104- bzrdir_format_name, repo_format.get_format_description())
105- self.repository_format = repo_format
106+ new_branch_format = target_branch._format
107+ if not new_branch_format.supports_stacking():
108+ new_branch_format = None
109+ if new_branch_format is not None:
110+ # Does support stacking, use its format.
111+ self.set_branch_format(new_branch_format)
112+ note('Source branch format does not support stacking,'
113+ ' using format:\n %s',
114+ new_branch_format.get_format_description())
115
116 def get_converter(self, format=None):
117 """See BzrDirFormat.get_converter()."""
118@@ -3532,54 +3601,9 @@
119 """
120 stack_on = self._get_full_stack_on()
121 if stack_on:
122- # Stacking is desired. requested by the target, but does the place it
123- # points at support stacking? If it doesn't then we should
124- # not implicitly upgrade. We check this here.
125 format = self._bzrdir._format
126- if not (format.repository_format.supports_external_lookups
127- and format.get_branch_format().supports_stacking()):
128- # May need to upgrade - but only do if the target also
129- # supports stacking. Note that this currently wastes
130- # network round trips to check - but we only do this
131- # when the source can't stack so it will fade away
132- # as people do upgrade.
133- branch_format = None
134- repo_format = None
135- try:
136- target_dir = BzrDir.open(stack_on,
137- possible_transports=[self._bzrdir.root_transport])
138- except errors.NotBranchError:
139- # Nothing there, don't change formats
140- pass
141- except errors.JailBreak:
142- # stack_on is inaccessible, JFDI.
143- if format.repository_format.rich_root_data:
144- repo_format = pack_repo.RepositoryFormatKnitPack6RichRoot()
145- else:
146- repo_format = pack_repo.RepositoryFormatKnitPack6()
147- branch_format = branch.BzrBranchFormat7()
148- else:
149- try:
150- target_branch = target_dir.open_branch()
151- except errors.NotBranchError:
152- # No branch, don't change formats
153- pass
154- else:
155- branch_format = target_branch._format
156- repo_format = target_branch.repository._format
157- if not (branch_format.supports_stacking()
158- and repo_format.supports_external_lookups):
159- # Doesn't stack itself, don't force an upgrade
160- branch_format = None
161- repo_format = None
162- if branch_format and repo_format:
163- # Does support stacking, use its format.
164- format.repository_format = repo_format
165- format.set_branch_format(branch_format)
166- note('Source format does not support stacking, '
167- 'using format: \'%s\'\n %s\n',
168- branch_format.get_format_description(),
169- repo_format.get_format_description())
170+ format.require_stacking(stack_on=stack_on,
171+ possible_transports=[self._bzrdir.root_transport])
172 if not self._require_stacking:
173 # We have picked up automatic stacking somewhere.
174 note('Using default stacking branch %s at %s', self._stack_on,
175
176=== modified file 'bzrlib/tests/blackbox/test_branch.py'
177--- bzrlib/tests/blackbox/test_branch.py 2009-04-15 04:45:06 +0000
178+++ bzrlib/tests/blackbox/test_branch.py 2009-06-04 02:35:11 +0000
179@@ -237,9 +237,10 @@
180 ['branch', '--stacked', 'trunk', 'shallow'])
181 # We should notify the user that we upgraded their format
182 self.assertEqualDiff(
183- 'Source format does not support stacking, using format: \'1.6\'\n'
184+ 'Source repository format does not support stacking, using format:\n'
185 ' Packs 5 (adds stacking support, requires bzr 1.6)\n'
186- '\n'
187+ 'Source branch format does not support stacking, using format:\n'
188+ ' Branch format 7\n'
189 'Created new stacked branch referring to %s.\n' % (trunk.base,),
190 err)
191
192@@ -249,10 +250,10 @@
193 ['branch', '--stacked', 'trunk', 'shallow'])
194 # We should notify the user that we upgraded their format
195 self.assertEqualDiff(
196- 'Source format does not support stacking, using format:'
197- ' \'1.6.1-rich-root\'\n'
198+ 'Source repository format does not support stacking, using format:\n'
199 ' Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
200- '\n'
201+ 'Source branch format does not support stacking, using format:\n'
202+ ' Branch format 7\n'
203 'Created new stacked branch referring to %s.\n' % (trunk.base,),
204 err)
205
206
207=== modified file 'bzrlib/tests/per_repository_reference/test_initialize.py'
208--- bzrlib/tests/per_repository_reference/test_initialize.py 2009-05-29 09:56:12 +0000
209+++ bzrlib/tests/per_repository_reference/test_initialize.py 2009-06-04 02:35:11 +0000
210@@ -52,8 +52,4 @@
211 trans = self.make_smart_server('stacked')
212 repo = self.initialize_and_check_on_transport(base, trans)
213 network_name = base.repository._format.network_name()
214- if network_name != repo._format.network_name():
215- raise tests.KnownFailure('Remote initialize_on_transport_ex()'
216- ' tries to "upgrade" the format because it doesn\'t have a'
217- ' branch format, and hard-codes the new repository format.')
218 self.assertEqual(network_name, repo._format.network_name())