~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/branch_implementations/test_tags.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
"""Tags stored within a branch
 
18
 
 
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.
 
21
"""
 
22
 
 
23
import os
 
24
import re
 
25
import sys
 
26
 
 
27
import bzrlib
 
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
 
33
 
 
34
from bzrlib.tests.branch_implementations.test_branch \
 
35
        import TestCaseWithBranch
 
36
 
 
37
 
 
38
class TestBranchTags(TestCaseWithBranch):
 
39
 
 
40
    def setUp(self):
 
41
        # formats that don't support tags can skip the rest of these 
 
42
        # tests...
 
43
        fmt = self.branch_format
 
44
        f = getattr(fmt, 'supports_tags')
 
45
        if f is None:
 
46
            raise TestSkipped("format %s doesn't declare whether it "
 
47
                "supports tags, assuming not" % fmt)
 
48
        if not f():
 
49
            raise TestSkipped("format %s doesn't support tags" % fmt)
 
50
        TestCaseWithBranch.setUp(self)
 
51
 
 
52
    def test_tags_initially_empty(self):
 
53
        b = self.make_branch('b')
 
54
        tags = b.tags.get_tag_dict()
 
55
        self.assertEqual(tags, {})
 
56
 
 
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
 
62
        b = Branch.open('b')
 
63
        self.assertEqual(b.tags.get_tag_dict(),
 
64
            {'tag-name': 'target-revid-1',
 
65
             'other-name': 'target-revid-2',
 
66
            })
 
67
        # read one at a time
 
68
        result = b.tags.lookup_tag('tag-name')
 
69
        self.assertEqual(result, 'target-revid-1')
 
70
        # and try has_tag
 
71
        self.assertTrue(b.tags.has_tag('tag-name'))
 
72
        self.assertFalse(b.tags.has_tag('imaginary'))
 
73
 
 
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
 
79
        b = Branch.open('b')
 
80
        self.assertEqual(b.tags.get_reverse_tag_dict(),
 
81
            {'target-revid-1': ['tag-name'],
 
82
             'target-revid-2': ['other-name'],
 
83
            })
 
84
 
 
85
    def test_no_such_tag(self):
 
86
        b = self.make_branch('b')
 
87
        try:
 
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')
 
92
        else:
 
93
            self.fail("didn't get expected exception")
 
94
 
 
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
 
99
        # just go across
 
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')
 
118
 
 
119
 
 
120
    def test_unicode_tag(self):
 
121
        b1 = self.make_branch('b')
 
122
        tag_name = u'\u3070'
 
123
        # in anticipation of the planned change to treating revision ids as
 
124
        # just 8bit strings
 
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)
 
128
 
 
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')
 
147
 
 
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)
 
153
 
 
154
 
 
155
class TestUnsupportedTags(TestCaseWithBranch):
 
156
    """Formats that don't support tags should give reasonable errors."""
 
157
 
 
158
    def setUp(self):
 
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"
 
163
                 % fmt)
 
164
            raise TestSkipped('No tag support at all')
 
165
        if supported():
 
166
            raise TestSkipped("Format %s declares that tags are supported"
 
167
                              % fmt)
 
168
            # it's covered by TestBranchTags
 
169
        TestCaseWithBranch.setUp(self)
 
170
    
 
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')
 
181
 
 
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)