~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_diff.py

  • Committer: Patch Queue Manager
  • Date: 2012-04-10 10:26:46 UTC
  • mfrom: (6519.1.2 responsefile-readline)
  • Revision ID: pqm@pqm.ubuntu.com-20120410102646-rv7zpi85e168o1k4
(jelmer) Implement ResponseFile.readline. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2012 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
 
18
 
"""Black-box tests for bzr diff.
19
 
"""
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
"""Black-box tests for bzr diff."""
20
19
 
21
20
import os
22
21
import re
23
22
 
24
 
import bzrlib
25
 
from bzrlib import workingtree
26
 
from bzrlib.branch import Branch
27
 
from bzrlib.tests import TestSkipped
28
 
from bzrlib.tests.blackbox import ExternalBase
 
23
from bzrlib import (
 
24
    tests,
 
25
    workingtree,
 
26
    )
 
27
from bzrlib.diff import (
 
28
    DiffTree,
 
29
    format_registry as diff_format_registry,
 
30
    )
 
31
from bzrlib.tests import (
 
32
    features,
 
33
    )
29
34
 
30
35
 
31
36
def subst_dates(string):
34
39
                  'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
35
40
 
36
41
 
37
 
class DiffBase(ExternalBase):
 
42
class DiffBase(tests.TestCaseWithTransport):
38
43
    """Base class with common setup method"""
39
44
 
40
45
    def make_example_branch(self):
41
 
        # FIXME: copied from test_too_much -- share elsewhere?
42
46
        tree = self.make_branch_and_tree('.')
43
 
        open('hello', 'wb').write('foo\n')
 
47
        self.build_tree_contents([
 
48
            ('hello', 'foo\n'),
 
49
            ('goodbye', 'baz\n')])
44
50
        tree.add(['hello'])
45
51
        tree.commit('setup')
46
 
        open('goodbye', 'wb').write('baz\n')
47
52
        tree.add(['goodbye'])
48
53
        tree.commit('setup')
 
54
        return tree
49
55
 
50
56
 
51
57
class TestDiff(DiffBase):
52
58
 
53
59
    def test_diff(self):
54
 
        self.make_example_branch()
55
 
        file('hello', 'wt').write('hello world!')
56
 
        self.run_bzr('commit -m fixing hello')
 
60
        tree = self.make_example_branch()
 
61
        self.build_tree_contents([('hello', 'hello world!')])
 
62
        tree.commit(message='fixing hello')
57
63
        output = self.run_bzr('diff -r 2..3', retcode=1)[0]
58
64
        self.assert_('\n+hello world!' in output)
59
 
        output = self.run_bzr('diff -r last:3..last:1',
60
 
                retcode=1)[0]
 
65
        output = self.run_bzr('diff -c 3', retcode=1)[0]
 
66
        self.assert_('\n+hello world!' in output)
 
67
        output = self.run_bzr('diff -r last:3..last:1', retcode=1)[0]
 
68
        self.assert_('\n+baz' in output)
 
69
        output = self.run_bzr('diff -c last:2', retcode=1)[0]
61
70
        self.assert_('\n+baz' in output)
62
71
        self.build_tree(['moo'])
63
 
        self.run_bzr('add moo')
 
72
        tree.add('moo')
64
73
        os.unlink('moo')
65
74
        self.run_bzr('diff')
66
75
 
67
76
    def test_diff_prefix(self):
68
77
        """diff --prefix appends to filenames in output"""
69
78
        self.make_example_branch()
70
 
        file('hello', 'wb').write('hello world!\n')
 
79
        self.build_tree_contents([('hello', 'hello world!\n')])
71
80
        out, err = self.run_bzr('diff --prefix old/:new/', retcode=1)
72
81
        self.assertEquals(err, '')
73
82
        self.assertEqualDiff(subst_dates(out), '''\
89
98
    def test_diff_p1(self):
90
99
        """diff -p1 produces lkml-style diffs"""
91
100
        self.make_example_branch()
92
 
        file('hello', 'wb').write('hello world!\n')
 
101
        self.build_tree_contents([('hello', 'hello world!\n')])
93
102
        out, err = self.run_bzr('diff -p1', retcode=1)
94
103
        self.assertEquals(err, '')
95
104
        self.assertEqualDiff(subst_dates(out), '''\
105
114
    def test_diff_p0(self):
106
115
        """diff -p0 produces diffs with no prefix"""
107
116
        self.make_example_branch()
108
 
        file('hello', 'wb').write('hello world!\n')
 
117
        self.build_tree_contents([('hello', 'hello world!\n')])
109
118
        out, err = self.run_bzr('diff -p0', retcode=1)
110
119
        self.assertEquals(err, '')
111
120
        self.assertEqualDiff(subst_dates(out), '''\
122
131
        # Get an error from a file that does not exist at all
123
132
        # (Malone #3619)
124
133
        self.make_example_branch()
125
 
        out, err = self.run_bzr('diff does-not-exist', retcode=3)
126
 
        self.assertContainsRe(err, 'not versioned.*does-not-exist')
 
134
        out, err = self.run_bzr('diff does-not-exist', retcode=3,
 
135
            error_regexes=('not versioned.*does-not-exist',))
127
136
 
128
137
    def test_diff_illegal_revision_specifiers(self):
129
 
        out, err = self.run_bzr('diff -r 1..23..123', retcode=3)
130
 
        self.assertContainsRe(err, 'one or two revision specifiers')
 
138
        out, err = self.run_bzr('diff -r 1..23..123', retcode=3,
 
139
            error_regexes=('one or two revision specifiers',))
 
140
 
 
141
    def test_diff_using_and_format(self):
 
142
        out, err = self.run_bzr('diff --format=default --using=mydi', retcode=3,
 
143
            error_regexes=('are mutually exclusive',))
 
144
 
 
145
    def test_diff_nonexistent_revision(self):
 
146
        out, err = self.run_bzr('diff -r 123', retcode=3,
 
147
            error_regexes=("Requested revision: '123' does not "
 
148
                "exist in branch:",))
 
149
 
 
150
    def test_diff_nonexistent_dotted_revision(self):
 
151
        out, err = self.run_bzr('diff -r 1.1', retcode=3)
 
152
        self.assertContainsRe(err,
 
153
            "Requested revision: '1.1' does not exist in branch:")
 
154
 
 
155
    def test_diff_nonexistent_dotted_revision_change(self):
 
156
        out, err = self.run_bzr('diff -c 1.1', retcode=3)
 
157
        self.assertContainsRe(err,
 
158
            "Requested revision: '1.1' does not exist in branch:")
131
159
 
132
160
    def test_diff_unversioned(self):
133
161
        # Get an error when diffing a non-versioned file.
140
168
    # TODO: What should diff say for a file deleted in working tree?
141
169
 
142
170
    def example_branches(self):
143
 
        self.build_tree(['branch1/', 'branch1/file'], line_endings='binary')
144
 
        self.run_bzr('init branch1')[0]
145
 
        self.run_bzr('add branch1/file')[0]
146
 
        self.run_bzr(['commit', '-m', 'add file', 'branch1'])
147
 
        self.run_bzr('branch branch1 branch2')[0]
 
171
        branch1_tree = self.make_branch_and_tree('branch1')
 
172
        self.build_tree(['branch1/file'], line_endings='binary')
 
173
        self.build_tree(['branch1/file2'], line_endings='binary')
 
174
        branch1_tree.add('file')
 
175
        branch1_tree.add('file2')
 
176
        branch1_tree.commit(message='add file and file2')
 
177
        branch2_tree = branch1_tree.bzrdir.sprout('branch2').open_workingtree()
148
178
        self.build_tree_contents([('branch2/file', 'new content\n')])
149
 
        self.run_bzr(['commit', '-m', 'update file', 'branch2'])
 
179
        branch2_tree.commit(message='update file')
 
180
        return branch1_tree, branch2_tree
150
181
 
151
 
    def test_diff_branches(self):
152
 
        self.example_branches()
153
 
        # should open branch1 and diff against branch2, 
154
 
        out, err = self.run_bzr('diff -r branch:branch2 branch1',
155
 
                                retcode=1)
 
182
    def check_b2_vs_b1(self, cmd):
 
183
        # Compare branch2 vs branch1 using cmd and check the result
 
184
        out, err = self.run_bzr(cmd, retcode=1)
156
185
        self.assertEquals('', err)
157
186
        self.assertEquals("=== modified file 'file'\n"
158
187
                          "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
161
190
                          "-new content\n"
162
191
                          "+contents of branch1/file\n"
163
192
                          "\n", subst_dates(out))
164
 
        out, err = self.run_bzr('diff branch2 branch1',
165
 
                                         retcode=1)
 
193
 
 
194
    def check_b1_vs_b2(self, cmd):
 
195
        # Compare branch1 vs branch2 using cmd and check the result
 
196
        out, err = self.run_bzr(cmd, retcode=1)
166
197
        self.assertEquals('', err)
167
198
        self.assertEqualDiff("=== modified file 'file'\n"
168
199
                              "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
169
200
                              "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
170
201
                              "@@ -1,1 +1,1 @@\n"
171
 
                              "-new content\n"
172
 
                              "+contents of branch1/file\n"
 
202
                              "-contents of branch1/file\n"
 
203
                              "+new content\n"
173
204
                              "\n", subst_dates(out))
174
205
 
 
206
    def check_no_diffs(self, cmd):
 
207
        # Check that running cmd returns an empty diff
 
208
        out, err = self.run_bzr(cmd, retcode=0)
 
209
        self.assertEquals('', err)
 
210
        self.assertEquals('', out)
 
211
 
 
212
    def test_diff_branches(self):
 
213
        self.example_branches()
 
214
        # should open branch1 and diff against branch2,
 
215
        self.check_b2_vs_b1('diff -r branch:branch2 branch1')
 
216
        # Compare two working trees using various syntax forms
 
217
        self.check_b2_vs_b1('diff --old branch2 --new branch1')
 
218
        self.check_b2_vs_b1('diff --old branch2 branch1')
 
219
        self.check_b2_vs_b1('diff branch2 --new branch1')
 
220
        # Test with a selected file that was changed
 
221
        self.check_b2_vs_b1('diff --old branch2 --new branch1 file')
 
222
        self.check_b2_vs_b1('diff --old branch2 branch1/file')
 
223
        self.check_b2_vs_b1('diff branch2/file --new branch1')
 
224
        # Test with a selected file that was not changed
 
225
        self.check_no_diffs('diff --old branch2 --new branch1 file2')
 
226
        self.check_no_diffs('diff --old branch2 branch1/file2')
 
227
        self.check_no_diffs('diff branch2/file2 --new branch1')
 
228
 
 
229
    def test_diff_branches_no_working_trees(self):
 
230
        branch1_tree, branch2_tree = self.example_branches()
 
231
        # Compare a working tree to a branch without a WT
 
232
        dir1 = branch1_tree.bzrdir
 
233
        dir1.destroy_workingtree()
 
234
        self.assertFalse(dir1.has_workingtree())
 
235
        self.check_b2_vs_b1('diff --old branch2 --new branch1')
 
236
        self.check_b2_vs_b1('diff --old branch2 branch1')
 
237
        self.check_b2_vs_b1('diff branch2 --new branch1')
 
238
        # Compare a branch without a WT to one with a WT
 
239
        self.check_b1_vs_b2('diff --old branch1 --new branch2')
 
240
        self.check_b1_vs_b2('diff --old branch1 branch2')
 
241
        self.check_b1_vs_b2('diff branch1 --new branch2')
 
242
        # Compare a branch with a WT against another without a WT
 
243
        dir2 = branch2_tree.bzrdir
 
244
        dir2.destroy_workingtree()
 
245
        self.assertFalse(dir2.has_workingtree())
 
246
        self.check_b1_vs_b2('diff --old branch1 --new branch2')
 
247
        self.check_b1_vs_b2('diff --old branch1 branch2')
 
248
        self.check_b1_vs_b2('diff branch1 --new branch2')
 
249
 
175
250
    def test_diff_revno_branches(self):
176
251
        self.example_branches()
177
 
        print >> open('branch2/file', 'wb'), 'even newer content'
178
 
        self.run_bzr(['commit', '-m',
179
 
                      'update file once more', 'branch2'])
 
252
        branch2_tree = workingtree.WorkingTree.open_containing('branch2')[0]
 
253
        self.build_tree_contents([('branch2/file', 'even newer content')])
 
254
        branch2_tree.commit(message='update file once more')
180
255
 
181
256
        out, err = self.run_bzr('diff -r revno:1:branch2..revno:1:branch1',
182
257
                                )
194
269
                              "\n", subst_dates(out))
195
270
 
196
271
    def example_branch2(self):
197
 
        self.build_tree(['branch1/', 'branch1/file1'], line_endings='binary')
198
 
        self.run_bzr('init branch1')[0]
199
 
        self.run_bzr('add branch1/file1')[0]
200
 
        print >> open('branch1/file1', 'wb'), 'original line'
201
 
        self.run_bzr(['commit', '-m', 'first commit', 'branch1'])
202
 
        
203
 
        print >> open('branch1/file1', 'wb'), 'repo line'
204
 
        self.run_bzr(['commit', '-m', 'second commit', 'branch1'])
 
272
        branch1_tree = self.make_branch_and_tree('branch1')
 
273
        self.build_tree_contents([('branch1/file1', 'original line\n')])
 
274
        branch1_tree.add('file1')
 
275
        branch1_tree.commit(message='first commit')
 
276
        self.build_tree_contents([('branch1/file1', 'repo line\n')])
 
277
        branch1_tree.commit(message='second commit')
 
278
        return branch1_tree
205
279
 
206
280
    def test_diff_to_working_tree(self):
207
281
        self.example_branch2()
208
 
        
209
 
        print >> open('branch1/file1', 'wb'), 'new line'
210
 
        output = self.run_bzr('diff -r 1.. branch1',
211
 
                              retcode=1)
212
 
        self.assertTrue('\n-original line\n+new line\n' in output[0])
 
282
        self.build_tree_contents([('branch1/file1', 'new line')])
 
283
        output = self.run_bzr('diff -r 1.. branch1', retcode=1)
 
284
        self.assertContainsRe(output[0], '\n\\-original line\n\\+new line\n')
 
285
 
 
286
    def test_diff_to_working_tree_in_subdir(self):
 
287
        self.example_branch2()
 
288
        self.build_tree_contents([('branch1/file1', 'new line')])
 
289
        os.mkdir('branch1/dir1')
 
290
        output = self.run_bzr('diff -r 1..', retcode=1,
 
291
                              working_dir='branch1/dir1')
 
292
        self.assertContainsRe(output[0], '\n\\-original line\n\\+new line\n')
213
293
 
214
294
    def test_diff_across_rename(self):
215
295
        """The working tree path should always be considered for diffing"""
216
 
        self.make_example_branch()
 
296
        tree = self.make_example_branch()
217
297
        self.run_bzr('diff -r 0..1 hello', retcode=1)
218
 
        wt = workingtree.WorkingTree.open_containing('.')[0]
219
 
        wt.rename_one('hello', 'hello1')
 
298
        tree.rename_one('hello', 'hello1')
220
299
        self.run_bzr('diff hello1', retcode=1)
221
300
        self.run_bzr('diff -r 0..1 hello1', retcode=1)
222
301
 
 
302
    def test_diff_to_branch_no_working_tree(self):
 
303
        branch1_tree = self.example_branch2()
 
304
        dir1 = branch1_tree.bzrdir
 
305
        dir1.destroy_workingtree()
 
306
        self.assertFalse(dir1.has_workingtree())
 
307
        output = self.run_bzr('diff -r 1.. branch1', retcode=1)
 
308
        self.assertContainsRe(output[0], '\n\\-original line\n\\+repo line\n')
 
309
 
 
310
    def test_custom_format(self):
 
311
        class BooDiffTree(DiffTree):
 
312
 
 
313
            def show_diff(self, specific_files, extra_trees=None):
 
314
                self.to_file.write("BOO!\n")
 
315
                return super(BooDiffTree, self).show_diff(specific_files,
 
316
                    extra_trees)
 
317
 
 
318
        diff_format_registry.register("boo", BooDiffTree, "Scary diff format")
 
319
        self.addCleanup(diff_format_registry.remove, "boo")
 
320
        self.make_example_branch()
 
321
        self.build_tree_contents([('hello', 'hello world!\n')])
 
322
        output = self.run_bzr('diff --format=boo', retcode=1)
 
323
        self.assertTrue("BOO!" in output[0])
 
324
        output = self.run_bzr('diff -Fboo', retcode=1)
 
325
        self.assertTrue("BOO!" in output[0])
 
326
 
223
327
 
224
328
class TestCheckoutDiff(TestDiff):
225
329
 
226
330
    def make_example_branch(self):
227
 
        super(TestCheckoutDiff, self).make_example_branch()
228
 
        self.run_bzr('checkout . checkout')
 
331
        tree = super(TestCheckoutDiff, self).make_example_branch()
 
332
        tree = tree.branch.create_checkout('checkout')
229
333
        os.chdir('checkout')
 
334
        return tree
230
335
 
231
336
    def example_branch2(self):
232
 
        super(TestCheckoutDiff, self).example_branch2()
 
337
        tree = super(TestCheckoutDiff, self).example_branch2()
233
338
        os.mkdir('checkouts')
234
 
        self.run_bzr('checkout branch1 checkouts/branch1')
 
339
        tree = tree.branch.create_checkout('checkouts/branch1')
235
340
        os.chdir('checkouts')
 
341
        return tree
236
342
 
237
343
    def example_branches(self):
238
 
        super(TestCheckoutDiff, self).example_branches()
 
344
        branch1_tree, branch2_tree = super(TestCheckoutDiff,
 
345
                                           self).example_branches()
239
346
        os.mkdir('checkouts')
240
 
        self.run_bzr('checkout branch1 checkouts/branch1')
241
 
        self.run_bzr('checkout branch2 checkouts/branch2')
 
347
        branch1_tree = branch1_tree.branch.create_checkout('checkouts/branch1')
 
348
        branch2_tree = branch2_tree.branch.create_checkout('checkouts/branch2')
242
349
        os.chdir('checkouts')
 
350
        return branch1_tree, branch2_tree
243
351
 
244
352
 
245
353
class TestDiffLabels(DiffBase):
246
354
 
247
355
    def test_diff_label_removed(self):
248
 
        super(TestDiffLabels, self).make_example_branch()
249
 
        self.run_bzr('remove hello')
 
356
        tree = super(TestDiffLabels, self).make_example_branch()
 
357
        tree.remove('hello', keep_files=False)
250
358
        diff = self.run_bzr('diff', retcode=1)
251
359
        self.assertTrue("=== removed file 'hello'" in diff[0])
252
360
 
253
361
    def test_diff_label_added(self):
254
 
        super(TestDiffLabels, self).make_example_branch()
255
 
        file('barbar', 'wt').write('barbar')
256
 
        self.run_bzr('add barbar')
 
362
        tree = super(TestDiffLabels, self).make_example_branch()
 
363
        self.build_tree_contents([('barbar', 'barbar')])
 
364
        tree.add('barbar')
257
365
        diff = self.run_bzr('diff', retcode=1)
258
366
        self.assertTrue("=== added file 'barbar'" in diff[0])
259
367
 
260
368
    def test_diff_label_modified(self):
261
369
        super(TestDiffLabels, self).make_example_branch()
262
 
        file('hello', 'wt').write('barbar')
 
370
        self.build_tree_contents([('hello', 'barbar')])
263
371
        diff = self.run_bzr('diff', retcode=1)
264
372
        self.assertTrue("=== modified file 'hello'" in diff[0])
265
373
 
266
374
    def test_diff_label_renamed(self):
267
 
        super(TestDiffLabels, self).make_example_branch()
268
 
        self.run_bzr('rename hello gruezi')
 
375
        tree = super(TestDiffLabels, self).make_example_branch()
 
376
        tree.rename_one('hello', 'gruezi')
269
377
        diff = self.run_bzr('diff', retcode=1)
270
378
        self.assertTrue("=== renamed file 'hello' => 'gruezi'" in diff[0])
271
379
 
274
382
 
275
383
    def test_external_diff(self):
276
384
        """Test that we can spawn an external diff process"""
 
385
        self.disable_missing_extensions_warning()
277
386
        # We have to use run_bzr_subprocess, because we need to
278
387
        # test writing directly to stdout, (there was a bug in
279
388
        # subprocess.py that we had to workaround).
280
389
        # However, if 'diff' may not be available
281
390
        self.make_example_branch()
282
 
        orig_progress = os.environ.get('BZR_PROGRESS_BAR')
283
 
        try:
284
 
            os.environ['BZR_PROGRESS_BAR'] = 'none'
285
 
            out, err = self.run_bzr_subprocess('diff', '-r', '1',
286
 
                                               '--diff-options', '-ub',
287
 
                                               universal_newlines=True,
288
 
                                               retcode=None)
289
 
        finally:
290
 
            if orig_progress is None:
291
 
                del os.environ['BZR_PROGRESS_BAR']
292
 
            else:
293
 
                os.environ['BZR_PROGRESS_BAR'] = orig_progress
294
 
            
 
391
        self.overrideEnv('BZR_PROGRESS_BAR', 'none')
 
392
        out, err = self.run_bzr_subprocess('diff -r 1 --diff-options -ub',
 
393
                                           universal_newlines=True,
 
394
                                           retcode=None)
295
395
        if 'Diff is not installed on this machine' in err:
296
 
            raise TestSkipped("No external 'diff' is available")
 
396
            raise tests.TestSkipped("No external 'diff' is available")
297
397
        self.assertEqual('', err)
298
398
        # We have to skip the stuff in the middle, because it depends
299
399
        # on time.time()
303
403
        self.assertEndsWith(out, "\n@@ -0,0 +1 @@\n"
304
404
                                 "+baz\n\n")
305
405
 
 
406
    def test_external_diff_options_and_using(self):
 
407
        """Test that the options are passed correctly to an external diff process"""
 
408
        self.requireFeature(features.diff_feature)
 
409
        self.make_example_branch()
 
410
        self.build_tree_contents([('hello', 'Foo\n')])
 
411
        out, err = self.run_bzr('diff --diff-options -i --using diff',
 
412
                                    retcode=1)
 
413
        self.assertEquals("=== modified file 'hello'\n", out)
 
414
        self.assertEquals('', err)
 
415
 
306
416
 
307
417
class TestDiffOutput(DiffBase):
308
418
 
309
419
    def test_diff_output(self):
310
420
        # check that output doesn't mangle line-endings
311
421
        self.make_example_branch()
312
 
        file('hello', 'wb').write('hello world!\n')
 
422
        self.build_tree_contents([('hello', 'hello world!\n')])
313
423
        output = self.run_bzr_subprocess('diff', retcode=1)[0]
314
424
        self.assert_('\n+hello world!\n' in output)