/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4597.9.5 by Vincent Ladeuil
Merge bzr.dev into cleanup
1
# Copyright (C) 2007-2010 Canonical Ltd
2225.1.1 by Aaron Bentley
Added revert change display, with tests
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2225.1.1 by Aaron Bentley
Added revert change display, with tests
16
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
17
import os
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
18
from cStringIO import StringIO
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
19
2225.1.1 by Aaron Bentley
Added revert change display, with tests
20
from bzrlib import (
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
21
    delta as _mod_delta,
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
22
    revision as _mod_revision,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
23
    tests,
24
    )
25
26
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
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
2225.1.4 by Aaron Bentley
PEP8 cleanup
36
2225.1.1 by Aaron Bentley
Added revert change display, with tests
37
class TestReportChanges(tests.TestCase):
2225.1.4 by Aaron Bentley
PEP8 cleanup
38
    """Test the new change reporting infrastructure"""
2225.1.1 by Aaron Bentley
Added revert change display, with tests
39
2225.1.3 by Aaron Bentley
change method names to assertFoo
40
    def assertReport(self, expected, file_id='fid', path='path',
41
                     versioned_change='unchanged', renamed=False,
42
                     modified='unchanged', exe_change=False,
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
43
                     kind=('file', 'file'), old_path=None,
3586.1.30 by Ian Clatworthy
add view support to change reporting
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):
2225.1.1 by Aaron Bentley
Added revert change display, with tests
60
        result = []
61
        def result_line(format, *args):
62
            result.append(format % args)
1551.10.25 by Aaron Bentley
Make ChangeReporter private
63
        reporter = _mod_delta._ChangeReporter(result_line,
3586.1.30 by Ian Clatworthy
add view support to change reporting
64
            unversioned_filter=unversioned_filter, view_info=view_info)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
65
        reporter.report(file_id, (old_path, path), versioned_change, renamed,
66
            modified, exe_change, kind)
3586.1.30 by Ian Clatworthy
add view support to change reporting
67
        if expected_lines is not None:
5422.3.8 by Martin Pool
Try for a better failure message in test_delta
68
            self.assertEqualDiff('\n'.join(expected_lines), '\n'.join(result))
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
69
        else:
70
            self.assertEqual([], result)
2225.1.1 by Aaron Bentley
Added revert change display, with tests
71
72
    def test_rename(self):
2225.1.3 by Aaron Bentley
change method names to assertFoo
73
        self.assertReport('R   old => path', renamed=True, old_path='old')
74
        self.assertReport('    path')
1551.10.12 by Aaron Bentley
Handle simultaneous creation+rename
75
        self.assertReport('RN  old => path', renamed=True, old_path='old',
76
                          modified='created', kind=(None, 'file'))
2225.1.1 by Aaron Bentley
Added revert change display, with tests
77
78
    def test_kind(self):
2225.1.3 by Aaron Bentley
change method names to assertFoo
79
        self.assertReport(' K  path => path/', modified='kind changed',
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
80
                          kind=('file', 'directory'), old_path='path')
2225.1.3 by Aaron Bentley
change method names to assertFoo
81
        self.assertReport(' K  path/ => path', modified='kind changed',
82
                          kind=('directory', 'file'), old_path='old')
83
        self.assertReport('RK  old => path/', renamed=True,
2225.1.5 by Aaron Bentley
Clean up whitespace changes
84
                          modified='kind changed',
2225.1.3 by Aaron Bentley
change method names to assertFoo
85
                          kind=('file', 'directory'), old_path='old')
2225.1.1 by Aaron Bentley
Added revert change display, with tests
86
    def test_new(self):
2225.1.3 by Aaron Bentley
change method names to assertFoo
87
        self.assertReport(' N  path/', modified='created',
88
                          kind=(None, 'directory'))
89
        self.assertReport('+   path/', versioned_change='added',
90
                          modified='unchanged', kind=(None, 'directory'))
1551.10.11 by Aaron Bentley
Handle case where file-id only is added
91
        self.assertReport('+   path', versioned_change='added',
92
                          modified='unchanged', kind=(None, None))
2225.1.3 by Aaron Bentley
change method names to assertFoo
93
        self.assertReport('+N  path/', versioned_change='added',
94
                          modified='created', kind=(None, 'directory'))
95
        self.assertReport('+M  path/', versioned_change='added',
96
                          modified='modified', kind=(None, 'directory'))
2225.1.1 by Aaron Bentley
Added revert change display, with tests
97
98
    def test_removal(self):
2225.1.3 by Aaron Bentley
change method names to assertFoo
99
        self.assertReport(' D  path/', modified='deleted',
100
                          kind=('directory', None), old_path='old')
101
        self.assertReport('-   path/', versioned_change='removed',
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
102
                          old_path='path',
2225.1.3 by Aaron Bentley
change method names to assertFoo
103
                          kind=(None, 'directory'))
104
        self.assertReport('-D  path', versioned_change='removed',
2255.2.232 by Robert Collins
Make WorkingTree4 report support for references based on the repositories capabilities.
105
                          old_path='path',
2225.1.3 by Aaron Bentley
change method names to assertFoo
106
                          modified='deleted', kind=('file', 'directory'))
2225.1.1 by Aaron Bentley
Added revert change display, with tests
107
108
    def test_modification(self):
2225.1.3 by Aaron Bentley
change method names to assertFoo
109
        self.assertReport(' M  path', modified='modified')
110
        self.assertReport(' M* path', modified='modified', exe_change=True)
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
111
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
112
    def test_unversioned(self):
113
        # by default any unversioned file is output
114
        self.assertReport('?   subdir/foo~', file_id=None, path='subdir/foo~',
115
            old_path=None, versioned_change='unversioned',
116
            renamed=False, modified='created', exe_change=False,
117
            kind=(None, 'file'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
118
        # but we can choose to filter these. Probably that should be done
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
119
        # close to the tree, but this is a reasonable starting point.
120
        self.assertReport(None, file_id=None, path='subdir/foo~',
121
            old_path=None, versioned_change='unversioned',
122
            renamed=False, modified='created', exe_change=False,
123
            kind=(None, 'file'), unversioned_filter=lambda x:True)
124
3586.1.30 by Ian Clatworthy
add view support to change reporting
125
    def test_view_filtering(self):
126
        # If a file in within the view, it should appear in the output
127
        expected_lines = [
128
            "Operating on whole tree but only reporting on 'my' view.",
129
            " M  path"]
130
        self.assertReportLines(expected_lines, modified='modified',
131
            view_info=('my',['path']))
132
        # If a file in outside the view, it should not appear in the output
133
        expected_lines = [
134
            "Operating on whole tree but only reporting on 'my' view."]
135
        self.assertReportLines(expected_lines, modified='modified',
136
            path="foo", view_info=('my',['path']))
137
2225.1.3 by Aaron Bentley
change method names to assertFoo
138
    def assertChangesEqual(self,
139
                           file_id='fid',
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
140
                           paths=('path', 'path'),
2225.1.3 by Aaron Bentley
change method names to assertFoo
141
                           content_change=False,
142
                           versioned=(True, True),
143
                           parent_id=('pid', 'pid'),
144
                           name=('name', 'name'),
145
                           kind=('file', 'file'),
146
                           executable=(False, False),
147
                           versioned_change='unchanged',
148
                           renamed=False,
149
                           modified='unchanged',
150
                           exe_change=False):
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
151
        reporter = InstrumentedReporter()
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
152
        _mod_delta.report_changes([(file_id, paths, content_change, versioned,
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
153
            parent_id, name, kind, executable)], reporter)
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
154
        output = reporter.calls[0]
155
        self.assertEqual(file_id, output[0])
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
156
        self.assertEqual(paths, output[1])
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
157
        self.assertEqual(versioned_change, output[2])
158
        self.assertEqual(renamed, output[3])
159
        self.assertEqual(modified, output[4])
160
        self.assertEqual(exe_change, output[5])
161
        self.assertEqual(kind, output[6])
162
163
    def test_report_changes(self):
164
        """Test change detection of report_changes"""
165
        #Ensure no changes are detected by default
2225.1.3 by Aaron Bentley
change method names to assertFoo
166
        self.assertChangesEqual(modified='unchanged', renamed=False,
167
                                versioned_change='unchanged',
168
                                exe_change=False)
169
        self.assertChangesEqual(modified='kind changed',
170
                                kind=('file', 'directory'))
171
        self.assertChangesEqual(modified='created', kind=(None, 'directory'))
172
        self.assertChangesEqual(modified='deleted', kind=('directory', None))
173
        self.assertChangesEqual(content_change=True, modified='modified')
174
        self.assertChangesEqual(renamed=True, name=('old', 'new'))
175
        self.assertChangesEqual(renamed=True,
176
                                parent_id=('old-parent', 'new-parent'))
177
        self.assertChangesEqual(versioned_change='added',
178
                                versioned=(False, True))
179
        self.assertChangesEqual(versioned_change='removed',
180
                                versioned=(True, False))
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
181
        # execute bit is only detected as "changed" if the file is and was
182
        # a regular file.
2225.1.3 by Aaron Bentley
change method names to assertFoo
183
        self.assertChangesEqual(exe_change=True, executable=(True, False))
184
        self.assertChangesEqual(exe_change=False, executable=(True, False),
185
                                kind=('directory', 'directory'))
186
        self.assertChangesEqual(exe_change=False, modified='kind changed',
187
                                executable=(False, True),
188
                                kind=('directory', 'file'))
1551.11.3 by Aaron Bentley
Use tree transform to emit upcoming change list
189
        self.assertChangesEqual(parent_id=('pid', None))
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
190
191
        # Now make sure they all work together
2225.1.3 by Aaron Bentley
change method names to assertFoo
192
        self.assertChangesEqual(versioned_change='removed',
193
                                modified='deleted', versioned=(True, False),
194
                                kind=('directory', None))
195
        self.assertChangesEqual(versioned_change='removed',
196
                                modified='created', versioned=(True, False),
197
                                kind=(None, 'file'))
198
        self.assertChangesEqual(versioned_change='removed',
199
                                modified='modified', renamed=True,
200
                                exe_change=True, versioned=(True, False),
201
                                content_change=True, name=('old', 'new'),
202
                                executable=(False, True))
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
203
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
204
    def test_report_unversioned(self):
205
        """Unversioned entries are reported well."""
206
        self.assertChangesEqual(file_id=None, paths=(None, 'full/path'),
207
                           content_change=True,
208
                           versioned=(False, False),
209
                           parent_id=(None, None),
210
                           name=(None, 'path'),
211
                           kind=(None, 'file'),
212
                           executable=(None, False),
213
                           versioned_change='unversioned',
214
                           renamed=False,
215
                           modified='created',
216
                           exe_change=False)
217
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
218
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
219
class TestChangesFrom(tests.TestCaseWithTransport):
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
220
221
    def show_string(self, delta, *args,  **kwargs):
222
        to_file = StringIO()
5076.4.8 by Arnaud Jeansen
Correct last delta.show() call in test_delta
223
        _mod_delta.report_delta(to_file, delta, *args, **kwargs)
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
224
        return to_file.getvalue()
225
226
    def test_kind_change(self):
227
        """Doing a status when a file has changed kind should work"""
228
        tree = self.make_branch_and_tree('.')
229
        self.build_tree(['filename'])
230
        tree.add('filename', 'file-id')
231
        tree.commit('added filename')
232
        os.unlink('filename')
233
        self.build_tree(['filename/'])
234
        delta = tree.changes_from(tree.basis_tree())
235
        self.assertEqual([('filename', 'file-id', 'file', 'directory')],
236
                         delta.kind_changed)
237
        self.assertEqual([], delta.added)
238
        self.assertEqual([], delta.removed)
239
        self.assertEqual([], delta.renamed)
240
        self.assertEqual([], delta.modified)
241
        self.assertEqual([], delta.unchanged)
242
        self.assertTrue(delta.has_changed())
243
        self.assertTrue(delta.touches_file_id('file-id'))
244
        self.assertEqual('kind changed:\n  filename (file => directory)\n',
245
                         self.show_string(delta))
246
        other_delta = _mod_delta.TreeDelta()
247
        self.assertNotEqual(other_delta, delta)
248
        other_delta.kind_changed = [('filename', 'file-id', 'file',
249
                                     'symlink')]
250
        self.assertNotEqual(other_delta, delta)
251
        other_delta.kind_changed = [('filename', 'file-id', 'file',
252
                                     'directory')]
253
        self.assertEqual(other_delta, delta)
254
        self.assertEqualDiff("TreeDelta(added=[], removed=[], renamed=[],"
255
            " kind_changed=[(u'filename', 'file-id', 'file', 'directory')],"
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
256
            " modified=[], unchanged=[], unversioned=[])", repr(delta))
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
257
        self.assertEqual('K  filename (file => directory) file-id\n',
258
                         self.show_string(delta, show_ids=True,
259
                         short_status=True))
260
261
        tree.rename_one('filename', 'dirname')
262
        delta = tree.changes_from(tree.basis_tree())
263
        self.assertEqual([], delta.kind_changed)
264
        # This loses the fact that kind changed, remembering it as a
265
        # modification
266
        self.assertEqual([('filename', 'dirname', 'file-id', 'directory',
267
                           True, False)], delta.renamed)
268
        self.assertTrue(delta.has_changed())
269
        self.assertTrue(delta.touches_file_id('file-id'))
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
270
271
272
class TestDeltaShow(tests.TestCaseWithTransport):
273
274
    def _get_delta(self):
275
        # We build the delta from a real tree to avoid depending on internal
276
        # implementation details.
277
        wt = self.make_branch_and_tree('branch')
278
        self.build_tree_contents([('branch/f1', '1\n'),
279
                                  ('branch/f2', '2\n'),
280
                                  ('branch/f3', '3\n'),
281
                                  ('branch/f4', '4\n'),
282
                                  ('branch/dir/',),
283
                                 ])
284
        wt.add(['f1', 'f2', 'f3', 'f4', 'dir'],
285
               ['f1-id', 'f2-id', 'f3-id', 'f4-id', 'dir-id'])
286
        wt.commit('commit one', rev_id='1')
287
288
        long_status = """added:
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
289
  dir/
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
290
  f1
291
  f2
292
  f3
293
  f4
294
"""
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
295
        short_status = """A  dir/
296
A  f1
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
297
A  f2
298
A  f3
299
A  f4
300
"""
301
302
        repo = wt.branch.repository
303
        d = wt.changes_from(repo.revision_tree(_mod_revision.NULL_REVISION))
304
        return d, long_status, short_status
305
306
    def test_delta_show_short_status_no_filter(self):
307
        d, long_status, short_status = self._get_delta()
308
        out = StringIO()
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
309
        _mod_delta.report_delta(out, d, short_status=True)
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
310
        self.assertEquals(short_status, out.getvalue())
311
312
    def test_delta_show_long_status_no_filter(self):
313
        d, long_status, short_status = self._get_delta()
314
        out = StringIO()
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
315
        _mod_delta.report_delta(out, d, short_status=False)
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
316
        self.assertEquals(long_status, out.getvalue())
317
318
    def test_delta_show_no_filter(self):
319
        d, long_status, short_status = self._get_delta()
320
        out = StringIO()
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
321
        def not_a_filter(path, file_id):
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
322
            return True
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
323
        _mod_delta.report_delta(out, d, short_status=True, filter=not_a_filter)
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
324
        self.assertEquals(short_status, out.getvalue())
325
326
    def test_delta_show_short_status_single_file_filter(self):
327
        d, long_status, short_status = self._get_delta()
328
        out = StringIO()
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
329
        def only_f2(path, file_id):
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
330
            return path == 'f2'
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
331
        _mod_delta.report_delta(out, d, short_status=True, filter=only_f2)
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
332
        self.assertEquals("A  f2\n", out.getvalue())
333
334
    def test_delta_show_long_status_single_file_filter(self):
335
        d, long_status, short_status = self._get_delta()
336
        out = StringIO()
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
337
        def only_f2(path, file_id):
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
338
            return path == 'f2'
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
339
        _mod_delta.report_delta(out, d, short_status=False, filter=only_f2)
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
340
        self.assertEquals("added:\n  f2\n", out.getvalue())
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
341
342
    def test_delta_show_short_status_single_file_id_filter(self):
343
        d, long_status, short_status = self._get_delta()
344
        out = StringIO()
345
        def only_f2_id(path, file_id):
346
            return file_id == 'f2-id'
5076.4.5 by Arnaud Jeansen
Ported test_delta to the report_delta method
347
        _mod_delta.report_delta(out, d, short_status=True, filter=only_f2_id)
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
348
        self.assertEquals("A  f2\n", out.getvalue())
349