~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Martin Pool
  • Date: 2010-01-29 10:36:23 UTC
  • mto: This revision was merged to the branch mainline in revision 4992.
  • Revision ID: mbp@sourcefrog.net-20100129103623-hywka5hymo5z13jw
Change url to canonical.com or wiki, plus some doc improvements in passing

Show diffs side-by-side

added added

removed removed

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