Merge lp:~jelmer/bzr/overwrite-tags into lp:bzr/2.5

Proposed by Jelmer Vernooij
Status: Rejected
Rejected by: Jelmer Vernooij
Proposed branch: lp:~jelmer/bzr/overwrite-tags
Merge into: lp:bzr/2.5
Diff against target: 202 lines (+80/-10)
6 files modified
bzrlib/branch.py (+20/-5)
bzrlib/builtins.py (+22/-3)
bzrlib/push.py (+2/-2)
bzrlib/tests/blackbox/test_pull.py (+17/-0)
bzrlib/tests/blackbox/test_push.py (+16/-0)
doc/en/release-notes/bzr-2.5.txt (+3/-0)
To merge this branch: bzr merge lp:~jelmer/bzr/overwrite-tags
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) Disapprove
Vincent Ladeuil Approve
Review via email: mp+91277@code.launchpad.net

Description of the change

Add --overwrite-tags argument to "bzr push" and "bzr pull".

I'm not entirely sure about the API change. I don't really want to end up with overwrite-history, overwrite-tags, overwrite-references, etc so using a tuple seemed reasonable. Users can still specify a boolean if they want to overwrite everything. Thoughts?

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

I'm not sure we're closing all holes here but until we have proper versioning for tags this seems like a valuable step.

Aren't we breaking plugins that redefine push/pull here ? (from irc discussion, yes :-/)

I think we need to think a bit more about it and re-targeting bzr.dev sounds more appropriate ?

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

Having slept on the topic, I had some more ideas.

My main objection here is that we break the API at the command-line level
which is bad for plugins overriding pull or push.

A less important objection is that the way we override the meaning of
--overwrite is a bit hackish and hard to document for plugins as well as
users.

A deeper one is that this smells like a work-around waiting for a more
robust story for tag handling which need to be versioned.

I can think of two ways to address these issues:

1) Create a specific Overwrite optparse option that will accept being used
as either: '--overwrite' or '--overwrite tags'. Internally we can still
consider that overwrite=False means nothing is overwritten and is a list of
components to overwrite otherwise. Since we used 'if overwrite' in the code
and 'overwrite=False' in signatures this should work.

This works less well as the command-line level as we need to make sure we
correctly interpret '--overwrite <url>' by leaving <url> alone (restricting
to 'tags' or ':tags', the latter avoiding ambiguities.

Not super user-friendly but workable.

2) We don't introduce an '--overwrite-tags' cmdline option but instead add
config options: 'pull.overwrite' and 'push.overwrite' defaulting to
'history,tags' (or 'revisions' instead of 'history' ?).

In this case, neither the cmdline interface is changed nor any internal
APIs, the interpretation of 'overwrite' is just delayed.

This seems less intrusive, will provide some help via 'bzr help
pull.overwrite' and is fully backward compatible.

This can then be used as 'bzr pull --overwrite -Opull.overwrite=tags'.

This proposal then becomes a bugfix that can very well land in 2.5.

Thoughts ?

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Am 03/02/12 09:55, schrieb Vincent Ladeuil:
> Having slept on the topic, I had some more ideas.
>
> My main objection here is that we break the API at the command-line level
> which is bad for plugins overriding pull or push.
Why is this a problem while if we're going to do another beta release?
AFAIK I'm the only person who works on plugins that override pull or
push, and I'm happy to do new releases of them before 2.5.0.
> A less important objection is that the way we override the meaning of
> --overwrite is a bit hackish and hard to document for plugins as well as
> users.
>
> A deeper one is that this smells like a work-around waiting for a more
> robust story for tag handling which need to be versioned.
>
> I can think of two ways to address these issues:
>
> 1) Create a specific Overwrite optparse option that will accept being used
> as either: '--overwrite' or '--overwrite tags'. Internally we can still
> consider that overwrite=False means nothing is overwritten and is a list of
> components to overwrite otherwise. Since we used 'if overwrite' in the code
> and 'overwrite=False' in signatures this should work.
>
> This works less well as the command-line level as we need to make sure we
> correctly interpret '--overwrite <url>' by leaving <url> alone (restricting
> to 'tags' or ':tags', the latter avoiding ambiguities.
>
> Not super user-friendly but workable.
Is it really a problem if we add an option (--overwrite-tags) that is
specific to formats with non-versioned tags? In the future it will just
become irrelevant for some formats, but it will stay useful for older
formats and some foreign formats anyway. Changing optparse seems much
more intrusive than just adding another option, and it's less well
discoverable.
> 2) We don't introduce an '--overwrite-tags' cmdline option but instead add
> config options: 'pull.overwrite' and 'push.overwrite' defaulting to
> 'history,tags' (or 'revisions' instead of 'history' ?).
>
> In this case, neither the cmdline interface is changed nor any internal
> APIs, the interpretation of 'overwrite' is just delayed.
>
> This seems less intrusive, will provide some help via 'bzr help
> pull.overwrite' and is fully backward compatible.
>
> This can then be used as 'bzr pull --overwrite -Opull.overwrite=tags'.
>
> This proposal then becomes a bugfix that can very well land in 2.5.
I don't see how this helps - it is still a contract change. This still
requires the foreign plugins to be updated, because they have to add
support for this option. Without support for that option in the foreign
plugins they will always just overwrite history and tags, which is just
as bad.

Cheers,

Jelmer

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

> Am 03/02/12 09:55, schrieb Vincent Ladeuil:
> > Having slept on the topic, I had some more ideas.
> >
> > My main objection here is that we break the API at the command-line level
> > which is bad for plugins overriding pull or push.
> Why is this a problem while if we're going to do another beta release?
> AFAIK I'm the only person who works on plugins that override pull or
> push, and I'm happy to do new releases of them before 2.5.0.

I don't think bzr-pipeline is impacted but what about bzr-loom ?

> > Not super user-friendly but workable.
> Is it really a problem if we add an option (--overwrite-tags) that is
> specific to formats with non-versioned tags? In the future it will just
> become irrelevant for some formats, but it will stay useful for older
> formats and some foreign formats anyway. Changing optparse seems much
> more intrusive than just adding another option, and it's less well
> discoverable.

I'm not talking about chnaging optparse, I'm talking of introducing a
specific option.

> > 2) We don't introduce an '--overwrite-tags' cmdline option but instead add
> > config options: 'pull.overwrite' and 'push.overwrite' defaulting to
> > 'history,tags' (or 'revisions' instead of 'history' ?).
> >
> > In this case, neither the cmdline interface is changed nor any internal
> > APIs, the interpretation of 'overwrite' is just delayed.
> >
> > This seems less intrusive, will provide some help via 'bzr help
> > pull.overwrite' and is fully backward compatible.
> >
> > This can then be used as 'bzr pull --overwrite -Opull.overwrite=tags'.
> >
> > This proposal then becomes a bugfix that can very well land in 2.5.

> I don't see how this helps - it is still a contract change.

A less intrusive one, that's the point. If the options are used with older
bzr, nothing happens.

> This still requires the foreign plugins to be updated, because they have
> to add support for this option.

How is your proposal different in this respect ?

These options also don't require updating the plugins unless they override
bzr internals. If they do they need to be updated whatever solution is used.

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 02/03/2012 02:10 PM, Vincent Ladeuil wrote:
>> Am 03/02/12 09:55, schrieb Vincent Ladeuil:
>>> Having slept on the topic, I had some more ideas.
>>>
>>> My main objection here is that we break the API at the command-line level
>>> which is bad for plugins overriding pull or push.
>> Why is this a problem while if we're going to do another beta release?
>> AFAIK I'm the only person who works on plugins that override pull or
>> push, and I'm happy to do new releases of them before 2.5.0.
>
> I don't think bzr-pipeline is impacted but what about bzr-loom ?
bzr-loom isn't impacted either as far as I can tell - it just passes
'overwrite' along as argument to the underlying Branch implementation.
>
>>> Not super user-friendly but workable.
>> Is it really a problem if we add an option (--overwrite-tags) that is
>> specific to formats with non-versioned tags? In the future it will just
>> become irrelevant for some formats, but it will stay useful for older
>> formats and some foreign formats anyway. Changing optparse seems much
>> more intrusive than just adding another option, and it's less well
>> discoverable.
>
> I'm not talking about chnaging optparse, I'm talking of introducing a
> specific option.
Still, it's changing an existing option and adding a bunch of logic to
deal with possible arguments to options. I don't see how that's better
than adding a new (more discoverable) option.

>
>>> 2) We don't introduce an '--overwrite-tags' cmdline option but
instead add
>>> config options: 'pull.overwrite' and 'push.overwrite' defaulting to
>>> 'history,tags' (or 'revisions' instead of 'history' ?).
>>>
>>> In this case, neither the cmdline interface is changed nor any internal
>>> APIs, the interpretation of 'overwrite' is just delayed.
>>>
>>> This seems less intrusive, will provide some help via 'bzr help
>>> pull.overwrite' and is fully backward compatible.
>>>
>>> This can then be used as 'bzr pull --overwrite -Opull.overwrite=tags'.
>>>
>>> This proposal then becomes a bugfix that can very well land in 2.5.
>
>> I don't see how this helps - it is still a contract change.
>
> A less intrusive one, that's the point. If the options are used with older
> bzr, nothing happens.
Something does happen, because history will be overwritten *too* (since
the underlying implementation doesn't look at pull.overwrite), not just
the tags. The same is the case with my change.

Also, isn't -O new in 2.5 anyway ?
>
>> This still requires the foreign plugins to be updated, because they have
>> to add support for this option.
>
> How is your proposal different in this respect ?
It isn't different in this respect, but neither does the alternative
provide any benefits in this regard.
> These options also don't require updating the plugins unless they override
> bzr internals. If they do they need to be updated whatever solution is
used.
Why do any plugins other than bzr-{svn,git,hg} have to be updated in the
case of my MP?

Cheers,

Jelmer

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Any chance of this in 2.5.1 perhaps?

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

Since versioned tags won't come soon, it makes sense to address the gap *now*, in 2.5, please land.

review: Approve
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

This can't land on 2.5 anymore since it's a fairly major API change that will break bzr-git, bzr-svn and bzr-hg.:-(

review: Disapprove

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/branch.py'
--- bzrlib/branch.py 2012-01-27 14:56:06 +0000
+++ bzrlib/branch.py 2012-02-02 14:31:53 +0000
@@ -3346,6 +3346,15 @@
3346 raise NotImplementedError(self.fetch)3346 raise NotImplementedError(self.fetch)
33473347
33483348
3349def _fix_overwrite_type(overwrite):
3350 if isinstance(overwrite, bool):
3351 if overwrite:
3352 return ["history", "tags"]
3353 else:
3354 return []
3355 return overwrite
3356
3357
3349class GenericInterBranch(InterBranch):3358class GenericInterBranch(InterBranch):
3350 """InterBranch implementation that uses public Branch functions."""3359 """InterBranch implementation that uses public Branch functions."""
33513360
@@ -3516,15 +3525,18 @@
3516 result.target_branch = self.target3525 result.target_branch = self.target
3517 result.old_revno, result.old_revid = self.target.last_revision_info()3526 result.old_revno, result.old_revid = self.target.last_revision_info()
3518 self.source.update_references(self.target)3527 self.source.update_references(self.target)
3528 overwrite = _fix_overwrite_type(overwrite)
3519 if result.old_revid != stop_revision:3529 if result.old_revid != stop_revision:
3520 # We assume that during 'push' this repository is closer than3530 # We assume that during 'push' this repository is closer than
3521 # the target.3531 # the target.
3522 graph = self.source.repository.get_graph(self.target.repository)3532 graph = self.source.repository.get_graph(self.target.repository)
3523 self._update_revisions(stop_revision, overwrite=overwrite,3533 self._update_revisions(stop_revision,
3524 graph=graph)3534 overwrite=("history" in overwrite),
3535 graph=graph)
3525 if self.source._push_should_merge_tags():3536 if self.source._push_should_merge_tags():
3526 result.tag_updates, result.tag_conflicts = (3537 result.tag_updates, result.tag_conflicts = (
3527 self.source.tags.merge_to(self.target.tags, overwrite))3538 self.source.tags.merge_to(
3539 self.target.tags, "tags" in overwrite))
3528 result.new_revno, result.new_revid = self.target.last_revision_info()3540 result.new_revno, result.new_revid = self.target.last_revision_info()
3529 return result3541 return result
35303542
@@ -3608,13 +3620,16 @@
3608 # -- JRV200905063620 # -- JRV20090506
3609 result.old_revno, result.old_revid = \3621 result.old_revno, result.old_revid = \
3610 self.target.last_revision_info()3622 self.target.last_revision_info()
3611 self._update_revisions(stop_revision, overwrite=overwrite,3623 overwrite = _fix_overwrite_type(overwrite)
3624 self._update_revisions(stop_revision,
3625 overwrite=("history" in overwrite),
3612 graph=graph)3626 graph=graph)
3613 # TODO: The old revid should be specified when merging tags, 3627 # TODO: The old revid should be specified when merging tags,
3614 # so a tags implementation that versions tags can only 3628 # so a tags implementation that versions tags can only
3615 # pull in the most recent changes. -- JRV200905063629 # pull in the most recent changes. -- JRV20090506
3616 result.tag_updates, result.tag_conflicts = (3630 result.tag_updates, result.tag_conflicts = (
3617 self.source.tags.merge_to(self.target.tags, overwrite,3631 self.source.tags.merge_to(self.target.tags,
3632 "tags" in overwrite,
3618 ignore_master=not merge_tags_to_master))3633 ignore_master=not merge_tags_to_master))
3619 result.new_revno, result.new_revid = self.target.last_revision_info()3634 result.new_revno, result.new_revid = self.target.last_revision_info()
3620 if _hook_master:3635 if _hook_master:
36213636
=== modified file 'bzrlib/builtins.py'
--- bzrlib/builtins.py 2012-01-31 15:43:17 +0000
+++ bzrlib/builtins.py 2012-02-02 14:31:53 +0000
@@ -1141,7 +1141,9 @@
1141 "the master branch."1141 "the master branch."
1142 ),1142 ),
1143 Option('show-base',1143 Option('show-base',
1144 help="Show base revision text in conflicts.")1144 help="Show base revision text in conflicts."),
1145 Option('overwrite-tags',
1146 help="Overwrite tags only."),
1145 ]1147 ]
1146 takes_args = ['location?']1148 takes_args = ['location?']
1147 encoding_type = 'replace'1149 encoding_type = 'replace'
@@ -1149,7 +1151,14 @@
1149 def run(self, location=None, remember=None, overwrite=False,1151 def run(self, location=None, remember=None, overwrite=False,
1150 revision=None, verbose=False,1152 revision=None, verbose=False,
1151 directory=None, local=False,1153 directory=None, local=False,
1152 show_base=False):1154 show_base=False, overwrite_tags=False):
1155
1156 if overwrite:
1157 overwrite = ["history", "tags"]
1158 elif overwrite_tags:
1159 overwrite = ["tags"]
1160 else:
1161 overwrite = []
1153 # FIXME: too much stuff is in the command class1162 # FIXME: too much stuff is in the command class
1154 revision_id = None1163 revision_id = None
1155 mergeable = None1164 mergeable = None
@@ -1291,6 +1300,8 @@
1291 Option('no-tree',1300 Option('no-tree',
1292 help="Don't populate the working tree, even for protocols"1301 help="Don't populate the working tree, even for protocols"
1293 " that support it."),1302 " that support it."),
1303 Option('overwrite-tags',
1304 help="Overwrite tags only."),
1294 ]1305 ]
1295 takes_args = ['location?']1306 takes_args = ['location?']
1296 encoding_type = 'replace'1307 encoding_type = 'replace'
@@ -1298,9 +1309,17 @@
1298 def run(self, location=None, remember=None, overwrite=False,1309 def run(self, location=None, remember=None, overwrite=False,
1299 create_prefix=False, verbose=False, revision=None,1310 create_prefix=False, verbose=False, revision=None,
1300 use_existing_dir=False, directory=None, stacked_on=None,1311 use_existing_dir=False, directory=None, stacked_on=None,
1301 stacked=False, strict=None, no_tree=False):1312 stacked=False, strict=None, no_tree=False,
1313 overwrite_tags=False):
1302 from bzrlib.push import _show_push_branch1314 from bzrlib.push import _show_push_branch
13031315
1316 if overwrite:
1317 overwrite = ["history", "tags"]
1318 elif overwrite_tags:
1319 overwrite = ["tags"]
1320 else:
1321 overwrite = []
1322
1304 if directory is None:1323 if directory is None:
1305 directory = '.'1324 directory = '.'
1306 # Get the source branch1325 # Get the source branch
13071326
=== modified file 'bzrlib/push.py'
--- bzrlib/push.py 2012-01-19 17:23:00 +0000
+++ bzrlib/push.py 2012-02-02 14:31:53 +0000
@@ -68,8 +68,8 @@
68 :param location: the url of the destination68 :param location: the url of the destination
69 :param to_file: the output stream69 :param to_file: the output stream
70 :param verbose: if True, display more output than normal70 :param verbose: if True, display more output than normal
71 :param overwrite: if False, a current branch at the destination may not71 :param overwrite: list of things to overwrite ("history", "tags")
72 have diverged from the source, otherwise the push fails72 or boolean indicating for everything
73 :param remember: if True, store the location as the push location for73 :param remember: if True, store the location as the push location for
74 the source branch74 the source branch
75 :param stacked_on: the url of the branch, if any, to stack on;75 :param stacked_on: the url of the branch, if any, to stack on;
7676
=== modified file 'bzrlib/tests/blackbox/test_pull.py'
--- bzrlib/tests/blackbox/test_pull.py 2012-01-05 17:46:44 +0000
+++ bzrlib/tests/blackbox/test_pull.py 2012-02-02 14:31:53 +0000
@@ -527,6 +527,23 @@
527 self.assertEqual(out,527 self.assertEqual(out,
528 ('1 tag(s) updated.\n', ''))528 ('1 tag(s) updated.\n', ''))
529529
530 def test_overwrite_tags(self):
531 """--overwrite-tags only overwrites tags, not revisions."""
532 from_tree = self.make_branch_and_tree('from')
533 from_tree.branch.tags.set_tag("mytag", "somerevid")
534 to_tree = self.make_branch_and_tree('to')
535 to_tree.branch.tags.set_tag("mytag", "anotherrevid")
536 revid1 = to_tree.commit('my commit')
537 out = self.run_bzr(['pull', '-d', 'to', 'from'], retcode=1)
538 self.assertEquals(out,
539 ('No revisions to pull.\nConflicting tags:\n mytag\n', ''))
540 out = self.run_bzr(['pull', '-d', 'to', '--overwrite-tags', 'from'])
541 self.assertEquals(out, ('1 tag(s) updated.\n', ''))
542
543 self.assertEquals(to_tree.branch.tags.lookup_tag('mytag'),
544 'somerevid')
545 self.assertEquals(to_tree.branch.last_revision(), revid1)
546
530 def test_pull_tag_overwrite(self):547 def test_pull_tag_overwrite(self):
531 """pulling tags with --overwrite only reports changed tags."""548 """pulling tags with --overwrite only reports changed tags."""
532 # create a branch, see that --show-base fails549 # create a branch, see that --show-base fails
533550
=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- bzrlib/tests/blackbox/test_push.py 2011-12-24 10:10:59 +0000
+++ bzrlib/tests/blackbox/test_push.py 2012-02-02 14:31:53 +0000
@@ -605,6 +605,22 @@
605 self.assertEqual('', out)605 self.assertEqual('', out)
606 self.assertEqual('Created new branch.\n', err)606 self.assertEqual('Created new branch.\n', err)
607607
608 def test_overwrite_tags(self):
609 """--overwrite-tags only overwrites tags, not revisions."""
610 from_tree = self.make_branch_and_tree('from')
611 from_tree.branch.tags.set_tag("mytag", "somerevid")
612 to_tree = self.make_branch_and_tree('to')
613 to_tree.branch.tags.set_tag("mytag", "anotherrevid")
614 revid1 = to_tree.commit('my commit')
615 out = self.run_bzr(['push', '-d', 'from', 'to'])
616 self.assertEquals(out,
617 ('Conflicting tags:\n mytag\n', 'No new revisions to push.\n'))
618 out = self.run_bzr(['push', '-d', 'from', '--overwrite-tags', 'to'])
619 self.assertEquals(out, ('', '1 tag updated.\n'))
620 self.assertEquals(to_tree.branch.tags.lookup_tag('mytag'),
621 'somerevid')
622 self.assertEquals(to_tree.branch.last_revision(), revid1)
623
608624
609class RedirectingMemoryTransport(memory.MemoryTransport):625class RedirectingMemoryTransport(memory.MemoryTransport):
610626
611627
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- doc/en/release-notes/bzr-2.5.txt 2012-02-01 17:41:55 +0000
+++ doc/en/release-notes/bzr-2.5.txt 2012-02-02 14:31:53 +0000
@@ -20,6 +20,9 @@
2020
21.. New commands, options, etc that users may wish to try out.21.. New commands, options, etc that users may wish to try out.
2222
23* New option ``--overwrite-tags`` for ``bzr pull`` and ``bzr push``.
24 (Jelmer Vernooij, #681792)
25
23* Support for colocated branches is now available in the default26* Support for colocated branches is now available in the default
24 format ("2a"). (Jelmer Vernooij)27 format ("2a"). (Jelmer Vernooij)
2528

Subscribers

People subscribed via source and target branches