/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_delta.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-18 18:18:36 UTC
  • mto: This revision was merged to the branch mainline in revision 4461.
  • Revision ID: john@arbash-meinel.com-20090618181836-biodfkat9a8eyzjz
The new add_inventory_by_delta is returning a CHKInventory when mapping from NULL
Which is completely valid, but 'broke' one of the tests.
So to fix it, changed the test to use CHKInventories on both sides, and add an __eq__
member. The nice thing is that CHKInventory.__eq__ is fairly cheap, since it only
has to check the root keys.

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
import os
 
18
from cStringIO import StringIO
 
19
 
 
20
from bzrlib import (
 
21
    delta as _mod_delta,
 
22
    revision as _mod_revision,
 
23
    tests,
 
24
    )
 
25
 
 
26
 
 
27
class InstrumentedReporter(object):
 
28
    def __init__(self):
 
29
        self.calls = []
 
30
 
 
31
    def report(self, file_id, path, versioned, renamed, modified, exe_change,
 
32
               kind):
 
33
        self.calls.append((file_id, path, versioned, renamed, modified,
 
34
                           exe_change, kind))
 
35
 
 
36
 
 
37
class TestReportChanges(tests.TestCase):
 
38
    """Test the new change reporting infrastructure"""
 
39
 
 
40
    def assertReport(self, expected, file_id='fid', path='path',
 
41
                     versioned_change='unchanged', renamed=False,
 
42
                     modified='unchanged', exe_change=False,
 
43
                     kind=('file', 'file'), old_path=None,
 
44
                     unversioned_filter=None, view_info=None):
 
45
        if expected is None:
 
46
            expected_lines = None
 
47
        else:
 
48
            expected_lines = [expected]
 
49
        self.assertReportLines(expected_lines, file_id, path,
 
50
                     versioned_change, renamed,
 
51
                     modified, exe_change,
 
52
                     kind, old_path,
 
53
                     unversioned_filter, view_info)
 
54
 
 
55
    def assertReportLines(self, expected_lines, file_id='fid', path='path',
 
56
                     versioned_change='unchanged', renamed=False,
 
57
                     modified='unchanged', exe_change=False,
 
58
                     kind=('file', 'file'), old_path=None,
 
59
                     unversioned_filter=None, view_info=None):
 
60
        result = []
 
61
        def result_line(format, *args):
 
62
            result.append(format % args)
 
63
        reporter = _mod_delta._ChangeReporter(result_line,
 
64
            unversioned_filter=unversioned_filter, view_info=view_info)
 
65
        reporter.report(file_id, (old_path, path), versioned_change, renamed,
 
66
            modified, exe_change, kind)
 
67
        if expected_lines is not None:
 
68
            for i in range(len(expected_lines)):
 
69
                self.assertEqualDiff(expected_lines[i], result[i])
 
70
        else:
 
71
            self.assertEqual([], result)
 
72
 
 
73
    def test_rename(self):
 
74
        self.assertReport('R   old => path', renamed=True, old_path='old')
 
75
        self.assertReport('    path')
 
76
        self.assertReport('RN  old => path', renamed=True, old_path='old',
 
77
                          modified='created', kind=(None, 'file'))
 
78
 
 
79
    def test_kind(self):
 
80
        self.assertReport(' K  path => path/', modified='kind changed',
 
81
                          kind=('file', 'directory'), old_path='path')
 
82
        self.assertReport(' K  path/ => path', modified='kind changed',
 
83
                          kind=('directory', 'file'), old_path='old')
 
84
        self.assertReport('RK  old => path/', renamed=True,
 
85
                          modified='kind changed',
 
86
                          kind=('file', 'directory'), old_path='old')
 
87
    def test_new(self):
 
88
        self.assertReport(' N  path/', modified='created',
 
89
                          kind=(None, 'directory'))
 
90
        self.assertReport('+   path/', versioned_change='added',
 
91
                          modified='unchanged', kind=(None, 'directory'))
 
92
        self.assertReport('+   path', versioned_change='added',
 
93
                          modified='unchanged', kind=(None, None))
 
94
        self.assertReport('+N  path/', versioned_change='added',
 
95
                          modified='created', kind=(None, 'directory'))
 
96
        self.assertReport('+M  path/', versioned_change='added',
 
97
                          modified='modified', kind=(None, 'directory'))
 
98
 
 
99
    def test_removal(self):
 
100
        self.assertReport(' D  path/', modified='deleted',
 
101
                          kind=('directory', None), old_path='old')
 
102
        self.assertReport('-   path/', versioned_change='removed',
 
103
                          old_path='path',
 
104
                          kind=(None, 'directory'))
 
105
        self.assertReport('-D  path', versioned_change='removed',
 
106
                          old_path='path',
 
107
                          modified='deleted', kind=('file', 'directory'))
 
108
 
 
109
    def test_modification(self):
 
110
        self.assertReport(' M  path', modified='modified')
 
111
        self.assertReport(' M* path', modified='modified', exe_change=True)
 
112
 
 
113
    def test_unversioned(self):
 
114
        # by default any unversioned file is output
 
115
        self.assertReport('?   subdir/foo~', file_id=None, path='subdir/foo~',
 
116
            old_path=None, versioned_change='unversioned',
 
117
            renamed=False, modified='created', exe_change=False,
 
118
            kind=(None, 'file'))
 
119
        # but we can choose to filter these. Probably that should be done
 
120
        # close to the tree, but this is a reasonable starting point.
 
121
        self.assertReport(None, file_id=None, path='subdir/foo~',
 
122
            old_path=None, versioned_change='unversioned',
 
123
            renamed=False, modified='created', exe_change=False,
 
124
            kind=(None, 'file'), unversioned_filter=lambda x:True)
 
125
 
 
126
    def test_view_filtering(self):
 
127
        # If a file in within the view, it should appear in the output
 
128
        expected_lines = [
 
129
            "Operating on whole tree but only reporting on 'my' view.",
 
130
            " M  path"]
 
131
        self.assertReportLines(expected_lines, modified='modified',
 
132
            view_info=('my',['path']))
 
133
        # If a file in outside the view, it should not appear in the output
 
134
        expected_lines = [
 
135
            "Operating on whole tree but only reporting on 'my' view."]
 
136
        self.assertReportLines(expected_lines, modified='modified',
 
137
            path="foo", view_info=('my',['path']))
 
138
 
 
139
    def assertChangesEqual(self,
 
140
                           file_id='fid',
 
141
                           paths=('path', 'path'),
 
142
                           content_change=False,
 
143
                           versioned=(True, True),
 
144
                           parent_id=('pid', 'pid'),
 
145
                           name=('name', 'name'),
 
146
                           kind=('file', 'file'),
 
147
                           executable=(False, False),
 
148
                           versioned_change='unchanged',
 
149
                           renamed=False,
 
150
                           modified='unchanged',
 
151
                           exe_change=False):
 
152
        reporter = InstrumentedReporter()
 
153
        _mod_delta.report_changes([(file_id, paths, content_change, versioned,
 
154
            parent_id, name, kind, executable)], reporter)
 
155
        output = reporter.calls[0]
 
156
        self.assertEqual(file_id, output[0])
 
157
        self.assertEqual(paths, output[1])
 
158
        self.assertEqual(versioned_change, output[2])
 
159
        self.assertEqual(renamed, output[3])
 
160
        self.assertEqual(modified, output[4])
 
161
        self.assertEqual(exe_change, output[5])
 
162
        self.assertEqual(kind, output[6])
 
163
 
 
164
    def test_report_changes(self):
 
165
        """Test change detection of report_changes"""
 
166
        #Ensure no changes are detected by default
 
167
        self.assertChangesEqual(modified='unchanged', renamed=False,
 
168
                                versioned_change='unchanged',
 
169
                                exe_change=False)
 
170
        self.assertChangesEqual(modified='kind changed',
 
171
                                kind=('file', 'directory'))
 
172
        self.assertChangesEqual(modified='created', kind=(None, 'directory'))
 
173
        self.assertChangesEqual(modified='deleted', kind=('directory', None))
 
174
        self.assertChangesEqual(content_change=True, modified='modified')
 
175
        self.assertChangesEqual(renamed=True, name=('old', 'new'))
 
176
        self.assertChangesEqual(renamed=True,
 
177
                                parent_id=('old-parent', 'new-parent'))
 
178
        self.assertChangesEqual(versioned_change='added',
 
179
                                versioned=(False, True))
 
180
        self.assertChangesEqual(versioned_change='removed',
 
181
                                versioned=(True, False))
 
182
        # execute bit is only detected as "changed" if the file is and was
 
183
        # a regular file.
 
184
        self.assertChangesEqual(exe_change=True, executable=(True, False))
 
185
        self.assertChangesEqual(exe_change=False, executable=(True, False),
 
186
                                kind=('directory', 'directory'))
 
187
        self.assertChangesEqual(exe_change=False, modified='kind changed',
 
188
                                executable=(False, True),
 
189
                                kind=('directory', 'file'))
 
190
        self.assertChangesEqual(parent_id=('pid', None))
 
191
 
 
192
        # Now make sure they all work together
 
193
        self.assertChangesEqual(versioned_change='removed',
 
194
                                modified='deleted', versioned=(True, False),
 
195
                                kind=('directory', None))
 
196
        self.assertChangesEqual(versioned_change='removed',
 
197
                                modified='created', versioned=(True, False),
 
198
                                kind=(None, 'file'))
 
199
        self.assertChangesEqual(versioned_change='removed',
 
200
                                modified='modified', renamed=True,
 
201
                                exe_change=True, versioned=(True, False),
 
202
                                content_change=True, name=('old', 'new'),
 
203
                                executable=(False, True))
 
204
 
 
205
    def test_report_unversioned(self):
 
206
        """Unversioned entries are reported well."""
 
207
        self.assertChangesEqual(file_id=None, paths=(None, 'full/path'),
 
208
                           content_change=True,
 
209
                           versioned=(False, False),
 
210
                           parent_id=(None, None),
 
211
                           name=(None, 'path'),
 
212
                           kind=(None, 'file'),
 
213
                           executable=(None, False),
 
214
                           versioned_change='unversioned',
 
215
                           renamed=False,
 
216
                           modified='created',
 
217
                           exe_change=False)
 
218
 
 
219
 
 
220
class TestChangesFrom(tests.TestCaseWithTransport):
 
221
 
 
222
    def show_string(self, delta, *args,  **kwargs):
 
223
        to_file = StringIO()
 
224
        delta.show(to_file, *args, **kwargs)
 
225
        return to_file.getvalue()
 
226
 
 
227
    def test_kind_change(self):
 
228
        """Doing a status when a file has changed kind should work"""
 
229
        tree = self.make_branch_and_tree('.')
 
230
        self.build_tree(['filename'])
 
231
        tree.add('filename', 'file-id')
 
232
        tree.commit('added filename')
 
233
        os.unlink('filename')
 
234
        self.build_tree(['filename/'])
 
235
        delta = tree.changes_from(tree.basis_tree())
 
236
        self.assertEqual([('filename', 'file-id', 'file', 'directory')],
 
237
                         delta.kind_changed)
 
238
        self.assertEqual([], delta.added)
 
239
        self.assertEqual([], delta.removed)
 
240
        self.assertEqual([], delta.renamed)
 
241
        self.assertEqual([], delta.modified)
 
242
        self.assertEqual([], delta.unchanged)
 
243
        self.assertTrue(delta.has_changed())
 
244
        self.assertTrue(delta.touches_file_id('file-id'))
 
245
        self.assertEqual('kind changed:\n  filename (file => directory)\n',
 
246
                         self.show_string(delta))
 
247
        other_delta = _mod_delta.TreeDelta()
 
248
        self.assertNotEqual(other_delta, delta)
 
249
        other_delta.kind_changed = [('filename', 'file-id', 'file',
 
250
                                     'symlink')]
 
251
        self.assertNotEqual(other_delta, delta)
 
252
        other_delta.kind_changed = [('filename', 'file-id', 'file',
 
253
                                     'directory')]
 
254
        self.assertEqual(other_delta, delta)
 
255
        self.assertEqualDiff("TreeDelta(added=[], removed=[], renamed=[],"
 
256
            " kind_changed=[(u'filename', 'file-id', 'file', 'directory')],"
 
257
            " modified=[], unchanged=[], unversioned=[])", repr(delta))
 
258
        self.assertEqual('K  filename (file => directory) file-id\n',
 
259
                         self.show_string(delta, show_ids=True,
 
260
                         short_status=True))
 
261
 
 
262
        tree.rename_one('filename', 'dirname')
 
263
        delta = tree.changes_from(tree.basis_tree())
 
264
        self.assertEqual([], delta.kind_changed)
 
265
        # This loses the fact that kind changed, remembering it as a
 
266
        # modification
 
267
        self.assertEqual([('filename', 'dirname', 'file-id', 'directory',
 
268
                           True, False)], delta.renamed)
 
269
        self.assertTrue(delta.has_changed())
 
270
        self.assertTrue(delta.touches_file_id('file-id'))
 
271
 
 
272
 
 
273
class TestDeltaShow(tests.TestCaseWithTransport):
 
274
 
 
275
    def _get_delta(self):
 
276
        # We build the delta from a real tree to avoid depending on internal
 
277
        # implementation details.
 
278
        wt = self.make_branch_and_tree('branch')
 
279
        self.build_tree_contents([('branch/f1', '1\n'),
 
280
                                  ('branch/f2', '2\n'),
 
281
                                  ('branch/f3', '3\n'),
 
282
                                  ('branch/f4', '4\n'),
 
283
                                  ('branch/dir/',),
 
284
                                 ])
 
285
        wt.add(['f1', 'f2', 'f3', 'f4', 'dir'],
 
286
               ['f1-id', 'f2-id', 'f3-id', 'f4-id', 'dir-id'])
 
287
        wt.commit('commit one', rev_id='1')
 
288
 
 
289
        long_status = """added:
 
290
  dir/
 
291
  f1
 
292
  f2
 
293
  f3
 
294
  f4
 
295
"""
 
296
        short_status = """A  dir/
 
297
A  f1
 
298
A  f2
 
299
A  f3
 
300
A  f4
 
301
"""
 
302
 
 
303
        repo = wt.branch.repository
 
304
        d = wt.changes_from(repo.revision_tree(_mod_revision.NULL_REVISION))
 
305
        return d, long_status, short_status
 
306
 
 
307
    def test_delta_show_short_status_no_filter(self):
 
308
        d, long_status, short_status = self._get_delta()
 
309
        out = StringIO()
 
310
        d.show(out, short_status=True)
 
311
        self.assertEquals(short_status, out.getvalue())
 
312
 
 
313
    def test_delta_show_long_status_no_filter(self):
 
314
        d, long_status, short_status = self._get_delta()
 
315
        out = StringIO()
 
316
        d.show(out, short_status=False)
 
317
        self.assertEquals(long_status, out.getvalue())
 
318
 
 
319
    def test_delta_show_no_filter(self):
 
320
        d, long_status, short_status = self._get_delta()
 
321
        out = StringIO()
 
322
        def not_a_filter(path, file_id):
 
323
            return True
 
324
        d.show(out, short_status=True, filter=not_a_filter)
 
325
        self.assertEquals(short_status, out.getvalue())
 
326
 
 
327
    def test_delta_show_short_status_single_file_filter(self):
 
328
        d, long_status, short_status = self._get_delta()
 
329
        out = StringIO()
 
330
        def only_f2(path, file_id):
 
331
            return path == 'f2'
 
332
        d.show(out, short_status=True, filter=only_f2)
 
333
        self.assertEquals("A  f2\n", out.getvalue())
 
334
 
 
335
    def test_delta_show_long_status_single_file_filter(self):
 
336
        d, long_status, short_status = self._get_delta()
 
337
        out = StringIO()
 
338
        def only_f2(path, file_id):
 
339
            return path == 'f2'
 
340
        d.show(out, short_status=False, filter=only_f2)
 
341
        self.assertEquals("added:\n  f2\n", out.getvalue())
 
342
 
 
343
    def test_delta_show_short_status_single_file_id_filter(self):
 
344
        d, long_status, short_status = self._get_delta()
 
345
        out = StringIO()
 
346
        def only_f2_id(path, file_id):
 
347
            return file_id == 'f2-id'
 
348
        d.show(out, short_status=True, filter=only_f2_id)
 
349
        self.assertEquals("A  f2\n", out.getvalue())
 
350