Rev 6128: (jelmer) Allow tag implementations to not support ghost revisions. (Jelmer in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Sep 6 10:11:57 UTC 2011
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 6128 [merge]
revision-id: pqm at pqm.ubuntu.com-20110906101154-46kb97u5tdj9enyi
parent: pqm at pqm.ubuntu.com-20110905194835-zadpgrm73dsrxrkd
parent: jelmer at samba.org-20110905211759-de03qv7b88po54n6
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2011-09-06 10:11:54 +0000
message:
(jelmer) Allow tag implementations to not support ghost revisions. (Jelmer
Vernooij)
modified:
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tag.py tag.py-20070212110532-91cw79inah2cfozx-1
bzrlib/tests/per_branch/test_tags.py test_tags.py-20070212110545-w2s799hm2jlbsmg5-1
doc/en/release-notes/bzr-2.5.txt bzr2.5.txt-20110708125756-587p0hpw7oke4h05-1
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2011-09-01 14:36:00 +0000
+++ b/bzrlib/branch.py 2011-09-05 14:16:12 +0000
@@ -1739,6 +1739,14 @@
"""True if this format supports tags stored in the branch"""
return False # by default
+ def tags_are_versioned(self):
+ """Whether the tag container for this branch versions tags."""
+ return False
+
+ def supports_tags_referencing_ghosts(self):
+ """True if tags can reference ghost revisions."""
+ return True
+
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
"""A factory for a BranchFormat object, permitting simple lazy registration.
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2011-08-21 13:49:30 +0000
+++ b/bzrlib/errors.py 2011-09-05 10:28:30 +0000
@@ -2349,6 +2349,14 @@
"""
+class GhostTagsNotSupported(BzrError):
+
+ _fmt = "Ghost tags not supported by format %(format)r."
+
+ def __init__(self, format):
+ self.format = format
+
+
class BinaryFile(BzrError):
_fmt = "File is binary but should be text."
=== modified file 'bzrlib/tag.py'
--- a/bzrlib/tag.py 2011-08-31 16:48:52 +0000
+++ b/bzrlib/tag.py 2011-09-05 14:16:12 +0000
@@ -47,6 +47,63 @@
def __init__(self, branch):
self.branch = branch
+ def get_tag_dict(self):
+ """Return a dictionary mapping tags to revision ids.
+ """
+ raise NotImplementedError(self.get_tag_dict)
+
+ def get_reverse_tag_dict(self):
+ """Return a dictionary mapping revision ids to list of tags.
+ """
+ raise NotImplementedError(self.get_reverse_tag_dict)
+
+ def merge_to(self, to_tags, overwrite=False, ignore_master=False):
+ """Merge new tags from this tags container into another.
+
+ :param to_tags: Tags container to merge into
+ :param overwrite: Whether to overwrite existing, divergent, tags.
+ :param ignore_master: Do not modify the tags in the target's master
+ branch (if any). Default is false (so the master will be updated).
+ New in bzr 2.3.
+ :return: Tuple with tag updates as dictionary and tag conflicts
+ """
+ raise NotImplementedError(self.merge_to)
+
+ def set_tag(self, tag_name, revision):
+ """Set a tag.
+
+ :param tag_name: Tag name
+ :param revision: Revision id
+ :raise GhostTagsNotSupported: if revision is not present in
+ the branch repository
+ """
+ raise NotImplementedError(self.set_tag)
+
+ def lookup_tag(self, tag_name):
+ """Look up a tag.
+
+ :param tag_name: Tag to look up
+ :raise NoSuchTag: Raised when tag does not exist
+ :return: Matching revision id
+ """
+ raise NotImplementedError(self.lookup_tag)
+
+ def delete_tag(self, tag_name):
+ """Delete a tag.
+
+ :param tag_name: Tag to delete
+ :raise NoSuchTag: Raised when tag does not exist
+ """
+ raise NotImplementedError(self.delete_tag)
+
+ def rename_revisions(self, rename_map):
+ """Replace revision ids according to a rename map.
+
+ :param rename_map: Dictionary mapping old revision ids to
+ new revision ids.
+ """
+ raise NotImplementedError(self.rename_revisions)
+
def has_tag(self, tag_name):
return self.get_tag_dict().has_key(tag_name)
@@ -262,7 +319,7 @@
def rename_revisions(self, rename_map):
"""Rename revisions in this tags dictionary.
-
+
:param rename_map: Dictionary mapping old revids to new revids
"""
reverse_tags = self.get_reverse_tag_dict()
=== modified file 'bzrlib/tests/per_branch/test_tags.py'
--- a/bzrlib/tests/per_branch/test_tags.py 2011-08-31 17:11:32 +0000
+++ b/bzrlib/tests/per_branch/test_tags.py 2011-09-05 21:17:59 +0000
@@ -22,6 +22,7 @@
from bzrlib import (
branch,
+ bzrdir as _mod_bzrdir,
errors,
tests,
)
@@ -39,13 +40,22 @@
raise tests.TestSkipped(
"format %s doesn't support tags" % branch._format)
+ def make_branch_with_revisions(self, relpath, revisions):
+ builder = self.make_branch_builder(relpath)
+ builder.start_series()
+ for revid in revisions:
+ builder.build_commit(rev_id=revid)
+ builder.finish_series()
+ return builder.get_branch()
+
def test_tags_initially_empty(self):
b = self.make_branch('b')
tags = b.tags.get_tag_dict()
self.assertEqual(tags, {})
def test_make_and_lookup_tag(self):
- b = self.make_branch('b')
+ b = self.make_branch_with_revisions('b',
+ ['target-revid-1', 'target-revid-2'])
b.tags.set_tag('tag-name', 'target-revid-1')
b.tags.set_tag('other-name', 'target-revid-2')
# then reopen the branch and see they're still there
@@ -62,16 +72,26 @@
self.assertFalse(b.tags.has_tag('imaginary'))
def test_reverse_tag_dict(self):
- b = self.make_branch('b')
+ b = self.make_branch_with_revisions('b',
+ ['target-revid-1', 'target-revid-2'])
b.tags.set_tag('tag-name', 'target-revid-1')
b.tags.set_tag('other-name', 'target-revid-2')
# then reopen the branch and check reverse map id->tags list
b = branch.Branch.open('b')
- self.assertEqual(b.tags.get_reverse_tag_dict(),
+ self.assertEqual(dict(b.tags.get_reverse_tag_dict()),
{'target-revid-1': ['tag-name'],
'target-revid-2': ['other-name'],
})
+ def test_ghost_tag(self):
+ b = self.make_branch('b')
+ if not b._format.supports_tags_referencing_ghosts():
+ self.assertRaises(errors.GhostTagsNotSupported,
+ b.tags.set_tag, "ghost", "idontexist")
+ else:
+ b.tags.set_tag("ghost", "idontexist")
+ self.assertEquals("idontexist", b.tags.lookup_tag("ghost"))
+
def test_no_such_tag(self):
b = self.make_branch('b')
try:
@@ -83,8 +103,8 @@
self.fail("didn't get expected exception")
def test_merge_tags(self):
- b1 = self.make_branch('b1')
- b2 = self.make_branch('b2')
+ b1 = self.make_branch_with_revisions('b1', ['revid', 'revid-1'])
+ b2 = self.make_branch_with_revisions('b2', ['revid-2'])
# if there are tags in the source and not the destination, then they
# just go across
b1.tags.set_tag('tagname', 'revid')
@@ -109,18 +129,18 @@
self.assertEquals(b2.tags.lookup_tag('conflicts'), 'revid-2')
def test_unicode_tag(self):
- b1 = self.make_branch('b')
tag_name = u'\u3070'
# in anticipation of the planned change to treating revision ids as
# just 8bit strings
revid = ('revid' + tag_name).encode('utf-8')
+ b1 = self.make_branch_with_revisions('b', [revid])
b1.tags.set_tag(tag_name, revid)
self.assertEquals(b1.tags.lookup_tag(tag_name), revid)
def test_delete_tag(self):
- b = self.make_branch('b')
tag_name = u'\N{GREEK SMALL LETTER ALPHA}'
revid = ('revid' + tag_name).encode('utf-8')
+ b = self.make_branch_with_revisions('b', [revid])
b.tags.set_tag(tag_name, revid)
# now try to delete it
b.tags.delete_tag(tag_name)
@@ -147,9 +167,10 @@
# Open the same branch twice. Read-lock one, and then mutate the tags
# in the second. The read-locked branch never re-reads the tags, so it
# never observes the changed/new tags.
- b1 = self.make_branch('b')
+ b1 = self.make_branch_with_revisions('b',
+ ['rev-1', 'rev-1-changed', 'rev-2'])
b1.tags.set_tag('one', 'rev-1')
- b2 = b1.bzrdir.open_branch()
+ b2 = _mod_bzrdir.BzrDir.open('b').open_branch()
b1.lock_read()
self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
# Add a tag and modify a tag in b2. b1 is read-locked and has already
@@ -166,7 +187,8 @@
def test_unlocked_does_not_cache_tags(self):
"""Unlocked branches do not cache tags."""
# Open the same branch twice.
- b1 = self.make_branch('b')
+ b1 = self.make_branch_with_revisions('b',
+ ['rev-1', 'rev-1-changed', 'rev-2'])
b1.tags.set_tag('one', 'rev-1')
b2 = b1.bzrdir.open_branch()
self.assertEqual({'one': 'rev-1'}, b1.tags.get_tag_dict())
@@ -182,7 +204,8 @@
returns a copy of the cached data so that callers cannot accidentally
corrupt the cache.
"""
- b = self.make_branch('b')
+ b = self.make_branch_with_revisions('b',
+ ['rev-1', 'rev-2', 'rev-3'])
b.tags.set_tag('one', 'rev-1')
self.addCleanup(b.lock_read().unlock)
# The first time the data returned will not be in the cache
@@ -196,7 +219,7 @@
self.assertEqual({'one': 'rev-1'}, b.tags.get_tag_dict())
def make_write_locked_branch_with_one_tag(self):
- b = self.make_branch('b')
+ b = self.make_branch_with_revisions('b', ['rev-1'])
b.tags.set_tag('one', 'rev-1')
self.addCleanup(b.lock_write().unlock)
# Populate the cache
@@ -462,7 +485,7 @@
get_tag_name, 'get tag name foo')
self.assertEquals("foo", self.branch.automatic_tag_name(
self.branch.last_revision()))
-
+
def test_uses_first_return(self):
get_tag_name_1 = lambda br, revid: "foo1"
get_tag_name_2 = lambda br, revid: "foo2"
=== modified file 'doc/en/release-notes/bzr-2.5.txt'
--- a/doc/en/release-notes/bzr-2.5.txt 2011-09-05 17:18:09 +0000
+++ b/doc/en/release-notes/bzr-2.5.txt 2011-09-06 10:11:54 +0000
@@ -225,6 +225,10 @@
value in SI format (i.e. "20MB", "1GB") into its integer equivalent.
(Shannon Weyrick)
+* ``Tags`` containers can now declare whether they support versioned
+ tags and whether tags can refer to ghost tags.
+ (Jelmer Vernooij)
+
* ``Tags.merge_to`` now returns a dictionary with the updated tags
and a set of conflicts, rather than just conflicts. (Jelmer Vernooij)
More information about the bazaar-commits
mailing list