1
# Copyright (C) 2007 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tags stored within a branch
19
The tags are actually in the Branch.tags namespace, but these are
20
1:1 with Branch implementations so can be tested from here.
28
from bzrlib import bzrdir, errors, repository
29
from bzrlib.branch import Branch, needs_read_lock, needs_write_lock
30
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
31
from bzrlib.trace import mutter
32
from bzrlib.workingtree import WorkingTree
34
from bzrlib.tests.branch_implementations.test_branch \
35
import TestCaseWithBranch
38
class TestBranchTags(TestCaseWithBranch):
41
# formats that don't support tags can skip the rest of these
43
fmt = self.branch_format
44
f = getattr(fmt, 'supports_tags')
46
raise TestSkipped("format %s doesn't declare whether it "
47
"supports tags, assuming not" % fmt)
49
raise TestSkipped("format %s doesn't support tags" % fmt)
50
TestCaseWithBranch.setUp(self)
52
def test_tags_initially_empty(self):
53
b = self.make_branch('b')
54
tags = b.tags.get_tag_dict()
55
self.assertEqual(tags, {})
57
def test_make_and_lookup_tag(self):
58
b = self.make_branch('b')
59
b.tags.set_tag('tag-name', 'target-revid-1')
60
b.tags.set_tag('other-name', 'target-revid-2')
61
# then reopen the branch and see they're still there
63
self.assertEqual(b.tags.get_tag_dict(),
64
{'tag-name': 'target-revid-1',
65
'other-name': 'target-revid-2',
68
result = b.tags.lookup_tag('tag-name')
69
self.assertEqual(result, 'target-revid-1')
71
self.assertTrue(b.tags.has_tag('tag-name'))
72
self.assertFalse(b.tags.has_tag('imaginary'))
74
def test_reverse_tag_dict(self):
75
b = self.make_branch('b')
76
b.tags.set_tag('tag-name', 'target-revid-1')
77
b.tags.set_tag('other-name', 'target-revid-2')
78
# then reopen the branch and check reverse map id->tags list
80
self.assertEqual(b.tags.get_reverse_tag_dict(),
81
{'target-revid-1': ['tag-name'],
82
'target-revid-2': ['other-name'],
85
def test_no_such_tag(self):
86
b = self.make_branch('b')
88
b.tags.lookup_tag('bosko')
89
except errors.NoSuchTag, e:
90
self.assertEquals(e.tag_name, 'bosko')
91
self.assertEquals(str(e), 'No such tag: bosko')
93
self.fail("didn't get expected exception")
95
def test_merge_tags(self):
96
b1 = self.make_branch('b1')
97
b2 = self.make_branch('b2')
98
# if there are tags in the source and not the destination, then they
100
b1.tags.set_tag('tagname', 'revid')
101
b1.tags.merge_to(b2.tags)
102
self.assertEquals(b2.tags.lookup_tag('tagname'), 'revid')
103
# if a tag is in the destination and not in the source, it is not
104
# removed when we merge them
105
b2.tags.set_tag('in-destination', 'revid')
106
result = b1.tags.merge_to(b2.tags)
107
self.assertEquals(result, [])
108
self.assertEquals(b2.tags.lookup_tag('in-destination'), 'revid')
109
# if there's a conflicting tag, it's reported -- the command line
110
# interface will say "these tags couldn't be copied"
111
b1.tags.set_tag('conflicts', 'revid-1')
112
b2.tags.set_tag('conflicts', 'revid-2')
113
result = b1.tags.merge_to(b2.tags)
114
self.assertEquals(result,
115
[('conflicts', 'revid-1', 'revid-2')])
116
# and it keeps the same value
117
self.assertEquals(b2.tags.lookup_tag('conflicts'), 'revid-2')
120
def test_unicode_tag(self):
121
b1 = self.make_branch('b')
123
# in anticipation of the planned change to treating revision ids as
125
revid = ('revid' + tag_name).encode('utf-8')
126
b1.tags.set_tag(tag_name, revid)
127
self.assertEquals(b1.tags.lookup_tag(tag_name), revid)
129
def test_delete_tag(self):
130
b = self.make_branch('b')
131
tag_name = u'\N{GREEK SMALL LETTER ALPHA}'
132
revid = ('revid' + tag_name).encode('utf-8')
133
b.tags.set_tag(tag_name, revid)
134
# now try to delete it
135
b.tags.delete_tag(tag_name)
136
# now you can't look it up
137
self.assertRaises(errors.NoSuchTag,
138
b.tags.lookup_tag, tag_name)
139
# and it's not in the dictionary
140
self.assertEquals(b.tags.get_tag_dict(), {})
141
# and you can't remove it a second time
142
self.assertRaises(errors.NoSuchTag,
143
b.tags.delete_tag, tag_name)
144
# or remove a tag that never existed
145
self.assertRaises(errors.NoSuchTag,
146
b.tags.delete_tag, tag_name + '2')
148
def test_merge_empty_tags(self):
149
# you can merge tags between two instances, since neither have tags
150
b1 = self.make_branch('b1')
151
b2 = self.make_branch('b2')
152
b1.tags.merge_to(b2.tags)
155
class TestUnsupportedTags(TestCaseWithBranch):
156
"""Formats that don't support tags should give reasonable errors."""
159
fmt = self.branch_format
160
supported = getattr(fmt, 'supports_tags')
161
if supported is None:
162
warn("Format %s doesn't declare whether it supports tags or not"
164
raise TestSkipped('No tag support at all')
166
raise TestSkipped("Format %s declares that tags are supported"
168
# it's covered by TestBranchTags
169
TestCaseWithBranch.setUp(self)
171
def test_tag_methods_raise(self):
172
b = self.make_branch('b')
173
self.assertRaises(errors.TagsNotSupported,
174
b.tags.set_tag, 'foo', 'bar')
175
self.assertRaises(errors.TagsNotSupported,
176
b.tags.lookup_tag, 'foo')
177
self.assertRaises(errors.TagsNotSupported,
178
b.tags.set_tag, 'foo', 'bar')
179
self.assertRaises(errors.TagsNotSupported,
180
b.tags.delete_tag, 'foo')
182
def test_merge_empty_tags(self):
183
# you can merge tags between two instances, since neither have tags
184
b1 = self.make_branch('b1')
185
b2 = self.make_branch('b2')
186
b1.tags.merge_to(b2.tags)