~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005, 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
18
"""Black-box tests for bzr diff.
19
"""
20
21
import os
1740.2.5 by Aaron Bentley
Merge from bzr.dev
22
import re
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
23
24
import bzrlib
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
25
from bzrlib import workingtree
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
26
from bzrlib.branch import Branch
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
27
from bzrlib.tests import TestSkipped
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
28
from bzrlib.tests.blackbox import ExternalBase
29
30
1740.2.5 by Aaron Bentley
Merge from bzr.dev
31
def subst_dates(string):
32
    """Replace date strings with constant values."""
33
    return re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}',
34
                  'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
35
36
2172.2.1 by Alexander Belchenko
Remove unnecessary duplication of tests in blackbox/test_diff.py
37
class DiffBase(ExternalBase):
38
    """Base class with common setup method"""
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
39
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
40
    def make_example_branch(self):
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
41
        # FIXME: copied from test_too_much -- share elsewhere?
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
42
        tree = self.make_branch_and_tree('.')
43
        open('hello', 'wb').write('foo\n')
44
        tree.add(['hello'])
45
        tree.commit('setup')
46
        open('goodbye', 'wb').write('baz\n')
47
        tree.add(['goodbye'])
48
        tree.commit('setup')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
49
2172.2.1 by Alexander Belchenko
Remove unnecessary duplication of tests in blackbox/test_diff.py
50
51
class TestDiff(DiffBase):
52
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
53
    def test_diff(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
54
        self.make_example_branch()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
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')
63
        os.unlink('moo')
64
        self.runbzr('diff')
65
1694.2.2 by Martin Pool
Add test for diff --diff-prefix, which was previously untested.
66
    def test_diff_prefix(self):
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
67
        """diff --prefix appends to filenames in output"""
68
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
69
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
70
        out, err = self.runbzr('diff --prefix old/:new/', retcode=1)
71
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
72
        self.assertEqualDiff(subst_dates(out), '''\
1694.2.4 by Martin Pool
When a diff prefix is given, don't show it in === summary lines, only on the diffs themselves.
73
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
74
--- old/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
75
+++ new/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
76
@@ -1,1 +1,1 @@
77
-foo
78
+hello world!
79
80
''')
81
2324.1.2 by Dmitry Vasiliev
Added test for bzr diff --prefix illegal_value
82
    def test_diff_illegal_prefix_value(self):
83
        # There was an error in error reporting for this option
84
        out, err = self.runbzr('diff --prefix old/', retcode=3)
85
        self.assertContainsRe(err,
86
            '--prefix expects two values separated by a colon')
87
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
88
    def test_diff_p1(self):
89
        """diff -p1 produces lkml-style diffs"""
90
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
91
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
92
        out, err = self.runbzr('diff -p1', retcode=1)
93
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
94
        self.assertEqualDiff(subst_dates(out), '''\
1694.2.4 by Martin Pool
When a diff prefix is given, don't show it in === summary lines, only on the diffs themselves.
95
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
96
--- old/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
97
+++ new/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
98
@@ -1,1 +1,1 @@
99
-foo
100
+hello world!
101
102
''')
103
104
    def test_diff_p0(self):
105
        """diff -p0 produces diffs with no prefix"""
106
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
107
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
108
        out, err = self.runbzr('diff -p0', retcode=1)
109
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
110
        self.assertEqualDiff(subst_dates(out), '''\
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
111
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
112
--- hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
113
+++ hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.2 by Martin Pool
Add test for diff --diff-prefix, which was previously untested.
114
@@ -1,1 +1,1 @@
115
-foo
116
+hello world!
117
118
''')
119
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
120
    def test_diff_nonexistent(self):
121
        # Get an error from a file that does not exist at all
122
        # (Malone #3619)
123
        self.make_example_branch()
124
        out, err = self.runbzr('diff does-not-exist', retcode=3)
125
        self.assertContainsRe(err, 'not versioned.*does-not-exist')
126
2197.2.1 by Martin Pool
Refactor cmd_diff
127
    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')
130
1658.1.10 by Martin Pool
diff on unversiond files should give an error (Malone #3619)
131
    def test_diff_unversioned(self):
132
        # Get an error when diffing a non-versioned file.
133
        # (Malone #3619)
134
        self.make_example_branch()
135
        self.build_tree(['unversioned-file'])
136
        out, err = self.runbzr('diff unversioned-file', retcode=3)
137
        self.assertContainsRe(err, 'not versioned.*unversioned-file')
138
139
    # TODO: What should diff say for a file deleted in working tree?
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
140
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
141
    def example_branches(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
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')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
147
        print >> open('branch2/file', 'wb'), 'new content'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
148
        self.run_bzr_captured(['commit', '-m', 'update file', 'branch2'])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
149
150
    def test_diff_branches(self):
151
        self.example_branches()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
152
        # should open branch1 and diff against branch2, 
1740.2.5 by Aaron Bentley
Merge from bzr.dev
153
        out, err = self.run_bzr_captured(['diff', '-r', 'branch:branch2', 
154
                                          'branch1'],
155
                                         retcode=1)
156
        self.assertEquals('', err)
157
        self.assertEquals("=== modified file 'file'\n"
158
                          "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
159
                          "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
160
                          "@@ -1,1 +1,1 @@\n"
161
                          "-new content\n"
162
                          "+contents of branch1/file\n"
163
                          "\n", subst_dates(out))
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
164
        out, err = self.run_bzr_captured(['diff', 'branch2', 'branch1'],
1740.2.5 by Aaron Bentley
Merge from bzr.dev
165
                                         retcode=1)
166
        self.assertEquals('', err)
167
        self.assertEqualDiff("=== modified file 'file'\n"
168
                              "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
169
                              "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
170
                              "@@ -1,1 +1,1 @@\n"
171
                              "-new content\n"
172
                              "+contents of branch1/file\n"
1740.2.5 by Aaron Bentley
Merge from bzr.dev
173
                              "\n", subst_dates(out))
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
174
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
175
    def test_diff_revno_branches(self):
176
        self.example_branches()
177
        print >> open('branch2/file', 'wb'), 'even newer content'
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
178
        self.run_bzr_captured(['commit', '-m', 
179
                               'update file once more', 'branch2'])
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
180
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
181
        out, err = self.run_bzr_captured(['diff', '-r',
182
                                          'revno:1:branch2..revno:1:branch1'],
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
183
                                         retcode=0)
184
        self.assertEquals('', err)
185
        self.assertEquals('', out)
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
186
        out, err = self.run_bzr_captured(['diff', '-r', 
187
                                          'revno:2:branch2..revno:1:branch1'],
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
188
                                         retcode=1)
189
        self.assertEquals('', err)
190
        self.assertEqualDiff("=== modified file 'file'\n"
191
                              "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
192
                              "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
193
                              "@@ -1,1 +1,1 @@\n"
194
                              "-new content\n"
195
                              "+contents of branch1/file\n"
196
                              "\n", subst_dates(out))
197
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
198
    def example_branch2(self):
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
199
        self.build_tree(['branch1/', 'branch1/file1'], line_endings='binary')
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
200
        self.capture('init branch1')
201
        self.capture('add branch1/file1')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
202
        print >> open('branch1/file1', 'wb'), 'original line'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
203
        self.run_bzr_captured(['commit', '-m', 'first commit', 'branch1'])
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
204
        
205
        print >> open('branch1/file1', 'wb'), 'repo line'
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
206
        self.run_bzr_captured(['commit', '-m', 'second commit', 'branch1'])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
207
208
    def test_diff_to_working_tree(self):
209
        self.example_branch2()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
210
        
211
        print >> open('branch1/file1', 'wb'), 'new line'
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
212
        output = self.run_bzr_captured(['diff', '-r', '1..', 'branch1'],
213
                                       retcode=1)
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
214
        self.assertTrue('\n-original line\n+new line\n' in output[0])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
215
1551.7.19 by Aaron Bentley
Always include working tree when calculating file ids for diff
216
    def test_diff_across_rename(self):
217
        """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)
224
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
225
226
class TestCheckoutDiff(TestDiff):
227
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
228
    def make_example_branch(self):
229
        super(TestCheckoutDiff, self).make_example_branch()
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
230
        self.runbzr('checkout . checkout')
231
        os.chdir('checkout')
232
233
    def example_branch2(self):
234
        super(TestCheckoutDiff, self).example_branch2()
235
        os.mkdir('checkouts')
236
        self.runbzr('checkout branch1 checkouts/branch1')
237
        os.chdir('checkouts')
238
239
    def example_branches(self):
240
        super(TestCheckoutDiff, self).example_branches()
241
        os.mkdir('checkouts')
242
        self.runbzr('checkout branch1 checkouts/branch1')
243
        self.runbzr('checkout branch2 checkouts/branch2')
244
        os.chdir('checkouts')
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
245
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
246
2172.2.1 by Alexander Belchenko
Remove unnecessary duplication of tests in blackbox/test_diff.py
247
class TestDiffLabels(DiffBase):
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
248
249
    def test_diff_label_removed(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
250
        super(TestDiffLabels, self).make_example_branch()
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
251
        self.runbzr('remove hello')
252
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
253
        self.assertTrue("=== removed file 'hello'" in diff[0])
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
254
255
    def test_diff_label_added(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
256
        super(TestDiffLabels, self).make_example_branch()
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
257
        file('barbar', 'wt').write('barbar')
258
        self.runbzr('add barbar')
259
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
260
        self.assertTrue("=== added file 'barbar'" in diff[0])
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
261
262
    def test_diff_label_modified(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
263
        super(TestDiffLabels, self).make_example_branch()
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
264
        file('hello', 'wt').write('barbar')
265
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
266
        self.assertTrue("=== modified file 'hello'" in diff[0])
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
267
268
    def test_diff_label_renamed(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
269
        super(TestDiffLabels, self).make_example_branch()
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
270
        self.runbzr('rename hello gruezi')
271
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
272
        self.assertTrue("=== renamed file 'hello' => 'gruezi'" in diff[0])
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
273
274
2172.2.1 by Alexander Belchenko
Remove unnecessary duplication of tests in blackbox/test_diff.py
275
class TestExternalDiff(DiffBase):
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
276
277
    def test_external_diff(self):
278
        """Test that we can spawn an external diff process"""
279
        # We have to use run_bzr_subprocess, because we need to
280
        # test writing directly to stdout, (there was a bug in
281
        # subprocess.py that we had to workaround).
282
        # However, if 'diff' may not be available
283
        self.make_example_branch()
284
        orig_progress = os.environ.get('BZR_PROGRESS_BAR')
285
        try:
286
            os.environ['BZR_PROGRESS_BAR'] = 'none'
2110.1.2 by John Arbash Meinel
Cleanup patch so it only adds universal_newlines
287
            out, err = self.run_bzr_subprocess('diff', '-r', '1',
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
288
                                               '--diff-options', '-ub',
2052.5.1 by Alexander Belchenko
blackbox.test_diff fix: don't load plugins when in test bzr run as subprocess
289
                                               universal_newlines=True,
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
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
            
297
        if 'Diff is not installed on this machine' in err:
298
            raise TestSkipped("No external 'diff' is available")
299
        self.assertEqual('', err)
300
        # We have to skip the stuff in the middle, because it depends
301
        # on time.time()
302
        self.assertStartsWith(out, "=== added file 'goodbye'\n"
303
                                   "--- goodbye\t1970-01-01 00:00:00 +0000\n"
304
                                   "+++ goodbye\t")
305
        self.assertEndsWith(out, "\n@@ -0,0 +1 @@\n"
1899.1.6 by John Arbash Meinel
internal_diff always adds a trailing \n, make sure external_diff does too
306
                                 "+baz\n\n")
2178.4.1 by Alexander Belchenko
Provide tests to illustrate bug #55276 on win32.
307
308
309
class TestDiffOutput(DiffBase):
310
311
    def test_diff_output(self):
2178.4.5 by Alexander Belchenko
Spell-checking (thanks to Aaron)
312
        # check that output doesn't mangle line-endings
2178.4.1 by Alexander Belchenko
Provide tests to illustrate bug #55276 on win32.
313
        self.make_example_branch()
314
        file('hello', 'wb').write('hello world!\n')
315
        output = self.run_bzr_subprocess('diff', retcode=1)[0]
316
        self.assert_('\n+hello world!\n' in output)