/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: Michael Ellerman
  • Date: 2006-05-31 08:44:29 UTC
  • mto: (1711.2.63 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1792.
  • Revision ID: michael@ellerman.id.au-20060531084429-35e5429abda9f560
Add optional location to ancestry and fix behaviour for checkouts.

This adds an optional location parameter to the ancestry command. It also
changes the behaviour of ancestry on checkouts such that if they have
been created with a subset of the branch history, only the subset is
shown by 'bzr ancestry'. Tests for all of that as well.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 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
 
        _mod_delta.report_delta(to_file, delta, *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
 
        _mod_delta.report_delta(out, d, 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
 
        _mod_delta.report_delta(out, d, 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
 
        _mod_delta.report_delta(out, d, 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
 
        _mod_delta.report_delta(out, d, 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
 
        _mod_delta.report_delta(out, d, 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
 
        _mod_delta.report_delta(out, d, short_status=True, filter=only_f2_id)
349
 
        self.assertEquals("A  f2\n", out.getvalue())
350