~bzr-pqm/bzr/bzr.dev

1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
1
# Copyright (C) 2005, 2006 by 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
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
37
class TestDiff(ExternalBase):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
38
1899.1.2 by John Arbash Meinel
Add a test that we can use an external diff program.
39
    def make_example_branch(self):
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
40
        # 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.
41
        tree = self.make_branch_and_tree('.')
42
        open('hello', 'wb').write('foo\n')
43
        tree.add(['hello'])
44
        tree.commit('setup')
45
        open('goodbye', 'wb').write('baz\n')
46
        tree.add(['goodbye'])
47
        tree.commit('setup')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
48
49
    def test_diff(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
50
        self.make_example_branch()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
51
        file('hello', 'wt').write('hello world!')
52
        self.runbzr('commit -m fixing hello')
53
        output = self.runbzr('diff -r 2..3', backtick=1, retcode=1)
54
        self.assert_('\n+hello world!' in output)
55
        output = self.runbzr('diff -r last:3..last:1', backtick=1, retcode=1)
56
        self.assert_('\n+baz' in output)
57
        file('moo', 'wb').write('moo')
58
        self.runbzr('add moo')
59
        os.unlink('moo')
60
        self.runbzr('diff')
61
1694.2.2 by Martin Pool
Add test for diff --diff-prefix, which was previously untested.
62
    def test_diff_prefix(self):
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
63
        """diff --prefix appends to filenames in output"""
64
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
65
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
66
        out, err = self.runbzr('diff --prefix old/:new/', retcode=1)
67
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
68
        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.
69
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
70
--- old/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
71
+++ new/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
72
@@ -1,1 +1,1 @@
73
-foo
74
+hello world!
75
76
''')
77
78
    def test_diff_p1(self):
79
        """diff -p1 produces lkml-style diffs"""
80
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
81
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
82
        out, err = self.runbzr('diff -p1', retcode=1)
83
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
84
        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.
85
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
86
--- old/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
87
+++ new/hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
88
@@ -1,1 +1,1 @@
89
-foo
90
+hello world!
91
92
''')
93
94
    def test_diff_p0(self):
95
        """diff -p0 produces diffs with no prefix"""
96
        self.make_example_branch()
1711.7.14 by John Arbash Meinel
diff tests check exact texts, should use binary mode for files.
97
        file('hello', 'wb').write('hello world!\n')
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
98
        out, err = self.runbzr('diff -p0', retcode=1)
99
        self.assertEquals(err, '')
1740.2.5 by Aaron Bentley
Merge from bzr.dev
100
        self.assertEqualDiff(subst_dates(out), '''\
1694.2.3 by Martin Pool
Add -p0, -p1 options for diff.
101
=== modified file 'hello'
1740.2.5 by Aaron Bentley
Merge from bzr.dev
102
--- hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
103
+++ hello\tYYYY-MM-DD HH:MM:SS +ZZZZ
1694.2.2 by Martin Pool
Add test for diff --diff-prefix, which was previously untested.
104
@@ -1,1 +1,1 @@
105
-foo
106
+hello world!
107
108
''')
109
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
110
    def test_diff_nonexistent(self):
111
        # Get an error from a file that does not exist at all
112
        # (Malone #3619)
113
        self.make_example_branch()
114
        out, err = self.runbzr('diff does-not-exist', retcode=3)
115
        self.assertContainsRe(err, 'not versioned.*does-not-exist')
116
1658.1.10 by Martin Pool
diff on unversiond files should give an error (Malone #3619)
117
    def test_diff_unversioned(self):
118
        # Get an error when diffing a non-versioned file.
119
        # (Malone #3619)
120
        self.make_example_branch()
121
        self.build_tree(['unversioned-file'])
122
        out, err = self.runbzr('diff unversioned-file', retcode=3)
123
        self.assertContainsRe(err, 'not versioned.*unversioned-file')
124
125
    # 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)
126
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
127
    def example_branches(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
128
        self.build_tree(['branch1/', 'branch1/file'], line_endings='binary')
129
        self.capture('init branch1')
130
        self.capture('add branch1/file')
131
        self.run_bzr_captured(['commit', '-m', 'add file', 'branch1'])
132
        self.capture('branch branch1 branch2')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
133
        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.
134
        self.run_bzr_captured(['commit', '-m', 'update file', 'branch2'])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
135
136
    def test_diff_branches(self):
137
        self.example_branches()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
138
        # should open branch1 and diff against branch2, 
1740.2.5 by Aaron Bentley
Merge from bzr.dev
139
        out, err = self.run_bzr_captured(['diff', '-r', 'branch:branch2', 
140
                                          'branch1'],
141
                                         retcode=1)
142
        self.assertEquals('', err)
143
        self.assertEquals("=== modified file 'file'\n"
144
                          "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
145
                          "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
146
                          "@@ -1,1 +1,1 @@\n"
147
                          "-new content\n"
148
                          "+contents of branch1/file\n"
149
                          "\n", subst_dates(out))
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
150
        out, err = self.run_bzr_captured(['diff', 'branch2', 'branch1'],
1740.2.5 by Aaron Bentley
Merge from bzr.dev
151
                                         retcode=1)
152
        self.assertEquals('', err)
153
        self.assertEqualDiff("=== modified file 'file'\n"
154
                              "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
155
                              "+++ 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.
156
                              "@@ -1,1 +1,1 @@\n"
157
                              "-new content\n"
158
                              "+contents of branch1/file\n"
1740.2.5 by Aaron Bentley
Merge from bzr.dev
159
                              "\n", subst_dates(out))
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
160
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
161
    def test_diff_revno_branches(self):
162
        self.example_branches()
163
        print >> open('branch2/file', 'wb'), 'even newer content'
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
164
        self.run_bzr_captured(['commit', '-m', 
165
                               'update file once more', 'branch2'])
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
166
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
167
        out, err = self.run_bzr_captured(['diff', '-r',
168
                                          'revno:1:branch2..revno:1:branch1'],
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
169
                                         retcode=0)
170
        self.assertEquals('', err)
171
        self.assertEquals('', out)
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
172
        out, err = self.run_bzr_captured(['diff', '-r', 
173
                                          'revno:2:branch2..revno:1:branch1'],
1732.3.3 by Matthieu Moy
Testcases for revno:N:path
174
                                         retcode=1)
175
        self.assertEquals('', err)
176
        self.assertEqualDiff("=== modified file 'file'\n"
177
                              "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
178
                              "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
179
                              "@@ -1,1 +1,1 @@\n"
180
                              "-new content\n"
181
                              "+contents of branch1/file\n"
182
                              "\n", subst_dates(out))
183
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
184
    def example_branch2(self):
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
185
        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.
186
        self.capture('init branch1')
187
        self.capture('add branch1/file1')
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
188
        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.
189
        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.
190
        
191
        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.
192
        self.run_bzr_captured(['commit', '-m', 'second commit', 'branch1'])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
193
194
    def test_diff_to_working_tree(self):
195
        self.example_branch2()
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
196
        
197
        print >> open('branch1/file1', 'wb'), 'new line'
1881.1.2 by Matthieu Moy
Formatting and style for the last patch.
198
        output = self.run_bzr_captured(['diff', '-r', '1..', 'branch1'],
199
                                       retcode=1)
1185.50.44 by John Arbash Meinel
[patch] Robey Pointer: diff -r 1.. should diff against working tree.
200
        self.assertTrue('\n-original line\n+new line\n' in output[0])
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
201
1551.7.19 by Aaron Bentley
Always include working tree when calculating file ids for diff
202
    def test_diff_across_rename(self):
203
        """The working tree path should always be considered for diffing"""
204
        self.make_example_branch()
205
        self.run_bzr('diff', '-r', '0..1', 'hello', retcode=1)
206
        wt = workingtree.WorkingTree.open_containing('.')[0]
207
        wt.rename_one('hello', 'hello1')
208
        self.run_bzr('diff', 'hello1', retcode=1)
209
        self.run_bzr('diff', '-r', '0..1', 'hello1', retcode=1)
210
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
211
212
class TestCheckoutDiff(TestDiff):
213
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
214
    def make_example_branch(self):
215
        super(TestCheckoutDiff, self).make_example_branch()
1551.2.13 by Aaron Bentley
Got diff working properly with checkouts
216
        self.runbzr('checkout . checkout')
217
        os.chdir('checkout')
218
219
    def example_branch2(self):
220
        super(TestCheckoutDiff, self).example_branch2()
221
        os.mkdir('checkouts')
222
        self.runbzr('checkout branch1 checkouts/branch1')
223
        os.chdir('checkouts')
224
225
    def example_branches(self):
226
        super(TestCheckoutDiff, self).example_branches()
227
        os.mkdir('checkouts')
228
        self.runbzr('checkout branch1 checkouts/branch1')
229
        self.runbzr('checkout branch2 checkouts/branch2')
230
        os.chdir('checkouts')
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
231
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
232
1583.1.1 by Michael Ellerman
Change to -p1 format diffs. Update existing tests to cope, and add some
233
class TestDiffLabels(TestDiff):
234
235
    def test_diff_label_removed(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
236
        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
237
        self.runbzr('remove hello')
238
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
239
        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
240
241
    def test_diff_label_added(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
242
        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
243
        file('barbar', 'wt').write('barbar')
244
        self.runbzr('add barbar')
245
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
246
        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
247
248
    def test_diff_label_modified(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
249
        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
250
        file('hello', 'wt').write('barbar')
251
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
252
        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
253
254
    def test_diff_label_renamed(self):
1658.1.9 by Martin Pool
Give an error for bzr diff on an nonexistent file (Malone #3619)
255
        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
256
        self.runbzr('rename hello gruezi')
257
        diff = self.run_bzr_captured(['diff'], retcode=1)
1694.2.1 by Martin Pool
Remove 'a/', 'b/' default prefixes on diff output.
258
        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.
259
260
261
class TestExternalDiff(TestDiff):
262
263
    def test_external_diff(self):
264
        """Test that we can spawn an external diff process"""
265
        # We have to use run_bzr_subprocess, because we need to
266
        # test writing directly to stdout, (there was a bug in
267
        # subprocess.py that we had to workaround).
268
        # However, if 'diff' may not be available
269
        self.make_example_branch()
270
        orig_progress = os.environ.get('BZR_PROGRESS_BAR')
271
        try:
272
            os.environ['BZR_PROGRESS_BAR'] = 'none'
273
            out, err = self.run_bzr_subprocess('diff', '-r', '1',
274
                                               '--diff-options', '-ub',
275
                                               retcode=None)
276
        finally:
277
            if orig_progress is None:
278
                del os.environ['BZR_PROGRESS_BAR']
279
            else:
280
                os.environ['BZR_PROGRESS_BAR'] = orig_progress
281
            
282
        if 'Diff is not installed on this machine' in err:
283
            raise TestSkipped("No external 'diff' is available")
284
        self.assertEqual('', err)
285
        # We have to skip the stuff in the middle, because it depends
286
        # on time.time()
287
        self.assertStartsWith(out, "=== added file 'goodbye'\n"
288
                                   "--- goodbye\t1970-01-01 00:00:00 +0000\n"
289
                                   "+++ goodbye\t")
290
        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
291
                                 "+baz\n\n")