~bzr-pqm/bzr/bzr.dev

4232.1.1 by Ian Clatworthy
Integrated EOL conversion support (Ian Clatworthy)
1
# Copyright (C) 2009 Canonical Ltd
4208.4.1 by Ian Clatworthy
eol conversion support
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
4232.1.1 by Ian Clatworthy
Integrated EOL conversion support (Ian Clatworthy)
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
4208.4.1 by Ian Clatworthy
eol conversion support
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
4232.1.1 by Ian Clatworthy
Integrated EOL conversion support (Ian Clatworthy)
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
4208.4.1 by Ian Clatworthy
eol conversion support
17
"""Tests for eol conversion."""
18
19
import sys
4393.3.3 by Ian Clatworthy
add round-trip checking to eol tests
20
from cStringIO import StringIO
4208.4.1 by Ian Clatworthy
eol conversion support
21
4393.3.3 by Ian Clatworthy
add round-trip checking to eol tests
22
from bzrlib import rules, status
4208.4.1 by Ian Clatworthy
eol conversion support
23
from bzrlib.tests import TestSkipped
4523.1.4 by Martin Pool
Rename remaining *_implementations tests
24
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
4208.4.1 by Ian Clatworthy
eol conversion support
25
from bzrlib.workingtree import WorkingTree
26
27
28
# Sample files
4208.4.3 by Ian Clatworthy
rename dos to windows
29
_sample_text         = """hello\nworld\r\n"""
30
_sample_text_on_win  = """hello\r\nworld\r\n"""
31
_sample_text_on_unix = """hello\nworld\n"""
32
_sample_binary       = """hello\nworld\r\n\x00"""
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
33
_sample_clean_lf     = _sample_text_on_unix
34
_sample_clean_crlf   = _sample_text_on_win
35
36
37
# Lists of formats for each storage policy
38
_LF_IN_REPO = ['native', 'lf', 'crlf']
39
_CRLF_IN_REPO = [ '%s-with-crlf-in-repo' % (f,) for f in _LF_IN_REPO]
4208.4.1 by Ian Clatworthy
eol conversion support
40
41
42
class TestEolConversion(TestCaseWithWorkingTree):
43
44
    def setUp(self):
45
        # formats that don't support content filtering can skip these tests
46
        fmt = self.workingtree_format
47
        f = getattr(fmt, 'supports_content_filtering')
48
        if f is None:
49
            raise TestSkipped("format %s doesn't declare whether it "
50
                "supports content filtering, assuming not" % fmt)
51
        if not f():
52
            raise TestSkipped("format %s doesn't support content filtering"
53
                % fmt)
6552.1.4 by Vincent Ladeuil
Remaining tests matching setup(self) that can be rewritten with super().
54
        super(TestEolConversion, self).setUp()
4208.4.1 by Ian Clatworthy
eol conversion support
55
56
    def patch_rules_searcher(self, eol):
57
        """Patch in a custom rules searcher with a given eol setting."""
58
        if eol is None:
59
            WorkingTree._get_rules_searcher = self.real_rules_searcher
60
        else:
61
            def custom_eol_rules_searcher(tree, default_searcher):
62
                return rules._IniBasedRulesSearcher([
63
                    '[name *]\n',
64
                    'eol=%s\n' % eol,
65
                    ])
66
            WorkingTree._get_rules_searcher = custom_eol_rules_searcher
67
68
    def prepare_tree(self, content, eol=None):
69
        """Prepare a working tree and commit some content."""
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
70
        self.real_rules_searcher = self.overrideAttr(
71
            WorkingTree, '_get_rules_searcher')
4208.4.1 by Ian Clatworthy
eol conversion support
72
        self.patch_rules_searcher(eol)
73
        t = self.make_branch_and_tree('tree1')
74
        self.build_tree_contents([('tree1/file1', content)])
75
        t.add('file1', 'file1-id')
76
        t.commit("add file1")
77
        basis = t.basis_tree()
78
        basis.lock_read()
79
        self.addCleanup(basis.unlock)
80
        return t, basis
81
4208.4.5 by Ian Clatworthy
add lf-always and crlf-always
82
    def assertNewContentForSetting(self, wt, eol, expected_unix,
4393.3.3 by Ian Clatworthy
add round-trip checking to eol tests
83
        expected_win, roundtrip):
84
        """Clone a working tree and check the convenience content.
85
        
86
        If roundtrip is True, status and commit should see no changes.
87
        """
4208.4.5 by Ian Clatworthy
add lf-always and crlf-always
88
        if expected_win is None:
89
            expected_win = expected_unix
4208.4.1 by Ian Clatworthy
eol conversion support
90
        self.patch_rules_searcher(eol)
91
        wt2 = wt.bzrdir.sprout('tree-%s' % eol).open_workingtree()
92
        # To see exactly what got written to disk, we need an unfiltered read
93
        content = wt2.get_file('file1-id', filtered=False).read()
94
        if sys.platform == 'win32':
4208.4.3 by Ian Clatworthy
rename dos to windows
95
            self.assertEqual(expected_win, content)
4208.4.1 by Ian Clatworthy
eol conversion support
96
        else:
97
            self.assertEqual(expected_unix, content)
4393.3.3 by Ian Clatworthy
add round-trip checking to eol tests
98
        # Confirm that status thinks nothing has changed if the text roundtrips
99
        if roundtrip:
100
            status_io = StringIO()
101
            status.show_tree_status(wt2, to_file=status_io)
102
            self.assertEqual('', status_io.getvalue())
4208.4.1 by Ian Clatworthy
eol conversion support
103
104
    def assertContent(self, wt, basis, expected_raw, expected_unix,
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
105
        expected_win, roundtrip_to=None):
106
        """Check the committed content and content in cloned trees.
107
        
108
        :param roundtrip_to: the set of formats (excluding exact) we
109
          can round-trip to or None for all
110
        """
4208.4.1 by Ian Clatworthy
eol conversion support
111
        basis_content = basis.get_file('file1-id').read()
112
        self.assertEqual(expected_raw, basis_content)
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
113
4393.3.3 by Ian Clatworthy
add round-trip checking to eol tests
114
        # No setting and exact should always roundtrip
115
        self.assertNewContentForSetting(wt, None,
116
            expected_raw, expected_raw, roundtrip=True)
117
        self.assertNewContentForSetting(wt, 'exact',
118
            expected_raw, expected_raw, roundtrip=True)
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
119
120
        # Roundtripping is otherwise dependent on whether the original
121
        # text is clean - mixed line endings will prevent it. It also
122
        # depends on whether the format in the repository is being changed.
123
        if roundtrip_to is None:
124
            roundtrip_to = _LF_IN_REPO + _CRLF_IN_REPO
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
125
        self.assertNewContentForSetting(wt, 'native',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
126
            expected_unix, expected_win, 'native' in roundtrip_to)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
127
        self.assertNewContentForSetting(wt, 'lf',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
128
            expected_unix, expected_unix, 'lf' in roundtrip_to)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
129
        self.assertNewContentForSetting(wt, 'crlf',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
130
            expected_win, expected_win, 'crlf' in roundtrip_to)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
131
        self.assertNewContentForSetting(wt, 'native-with-crlf-in-repo',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
132
            expected_unix, expected_win,
133
            'native-with-crlf-in-repo' in roundtrip_to)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
134
        self.assertNewContentForSetting(wt, 'lf-with-crlf-in-repo',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
135
            expected_unix, expected_unix,
136
            'lf-with-crlf-in-repo' in roundtrip_to)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
137
        self.assertNewContentForSetting(wt, 'crlf-with-crlf-in-repo',
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
138
            expected_win, expected_win,
139
            'crlf-with-crlf-in-repo' in roundtrip_to)
140
141
    # Test binary files. These always roundtrip.
142
143
    def test_eol_no_rules_binary(self):
144
        wt, basis = self.prepare_tree(_sample_binary)
145
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
146
            _sample_binary)
147
148
    def test_eol_exact_binary(self):
149
        wt, basis = self.prepare_tree(_sample_binary, eol='exact')
150
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
151
            _sample_binary)
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
152
153
    def test_eol_native_binary(self):
154
        wt, basis = self.prepare_tree(_sample_binary, eol='native')
155
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
156
            _sample_binary)
157
4208.4.4 by Ian Clatworthy
unix/window -> cr/crlf based on mailing list feedback
158
    def test_eol_lf_binary(self):
159
        wt, basis = self.prepare_tree(_sample_binary, eol='lf')
4208.4.3 by Ian Clatworthy
rename dos to windows
160
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
161
            _sample_binary)
162
4208.4.4 by Ian Clatworthy
unix/window -> cr/crlf based on mailing list feedback
163
    def test_eol_crlf_binary(self):
164
        wt, basis = self.prepare_tree(_sample_binary, eol='crlf')
4208.4.3 by Ian Clatworthy
rename dos to windows
165
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
166
            _sample_binary)
4208.4.1 by Ian Clatworthy
eol conversion support
167
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
168
    def test_eol_native_with_crlf_in_repo_binary(self):
169
        wt, basis = self.prepare_tree(_sample_binary,
170
            eol='native-with-crlf-in-repo')
171
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
172
            _sample_binary)
173
174
    def test_eol_lf_with_crlf_in_repo_binary(self):
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
175
        wt, basis = self.prepare_tree(_sample_binary,
176
            eol='lf-with-crlf-in-repo')
4208.4.7 by Ian Clatworthy
tweak eol names based on mailing list discussion
177
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
178
            _sample_binary)
179
180
    def test_eol_crlf_with_crlf_in_repo_binary(self):
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
181
        wt, basis = self.prepare_tree(_sample_binary,
182
            eol='crlf-with-crlf-in-repo')
4208.4.5 by Ian Clatworthy
add lf-always and crlf-always
183
        self.assertContent(wt, basis, _sample_binary, _sample_binary,
184
            _sample_binary)
185
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
186
    # Test text with mixed line endings ("dirty text").
187
    # This doesn't roundtrip so status always thinks something has changed.
188
189
    def test_eol_no_rules_dirty(self):
190
        wt, basis = self.prepare_tree(_sample_text)
191
        self.assertContent(wt, basis, _sample_text,
192
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
193
194
    def test_eol_exact_dirty(self):
4208.4.3 by Ian Clatworthy
rename dos to windows
195
        wt, basis = self.prepare_tree(_sample_text, eol='exact')
196
        self.assertContent(wt, basis, _sample_text,
4393.3.4 by Ian Clatworthy
add eol roundtripping tests
197
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
198
199
    def test_eol_native_dirty(self):
200
        wt, basis = self.prepare_tree(_sample_text, eol='native')
201
        self.assertContent(wt, basis, _sample_text_on_unix,
202
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
203
204
    def test_eol_lf_dirty(self):
205
        wt, basis = self.prepare_tree(_sample_text, eol='lf')
206
        self.assertContent(wt, basis, _sample_text_on_unix,
207
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
208
209
    def test_eol_crlf_dirty(self):
210
        wt, basis = self.prepare_tree(_sample_text, eol='crlf')
211
        self.assertContent(wt, basis, _sample_text_on_unix,
212
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
213
214
    def test_eol_native_with_crlf_in_repo_dirty(self):
215
        wt, basis = self.prepare_tree(_sample_text,
216
            eol='native-with-crlf-in-repo')
217
        self.assertContent(wt, basis, _sample_text_on_win,
218
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
219
220
    def test_eol_lf_with_crlf_in_repo_dirty(self):
221
        wt, basis = self.prepare_tree(_sample_text,
222
            eol='lf-with-crlf-in-repo')
223
        self.assertContent(wt, basis, _sample_text_on_win,
224
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
225
226
    def test_eol_crlf_with_crlf_in_repo_dirty(self):
227
        wt, basis = self.prepare_tree(_sample_text,
228
            eol='crlf-with-crlf-in-repo')
229
        self.assertContent(wt, basis, _sample_text_on_win,
230
            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
231
232
    # Test text with clean line endings, either always lf or always crlf.
233
    # This selectively roundtrips (based on what's stored in the repo).
234
235
    def test_eol_no_rules_clean_lf(self):
236
        wt, basis = self.prepare_tree(_sample_clean_lf)
237
        self.assertContent(wt, basis, _sample_clean_lf,
238
            _sample_text_on_unix, _sample_text_on_win,
239
            roundtrip_to=_LF_IN_REPO)
240
241
    def test_eol_no_rules_clean_crlf(self):
242
        wt, basis = self.prepare_tree(_sample_clean_crlf)
243
        self.assertContent(wt, basis, _sample_clean_crlf,
244
            _sample_text_on_unix, _sample_text_on_win,
245
            roundtrip_to=_CRLF_IN_REPO)
246
247
    def test_eol_exact_clean_lf(self):
248
        wt, basis = self.prepare_tree(_sample_clean_lf, eol='exact')
249
        self.assertContent(wt, basis, _sample_clean_lf,
250
            _sample_text_on_unix, _sample_text_on_win,
251
            roundtrip_to=_LF_IN_REPO)
252
253
    def test_eol_exact_clean_crlf(self):
254
        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='exact')
255
        self.assertContent(wt, basis, _sample_clean_crlf,
256
            _sample_text_on_unix, _sample_text_on_win,
257
            roundtrip_to=_CRLF_IN_REPO)
258
259
    def test_eol_native_clean_lf(self):
260
        wt, basis = self.prepare_tree(_sample_clean_lf, eol='native')
261
        self.assertContent(wt, basis, _sample_text_on_unix,
262
            _sample_text_on_unix, _sample_text_on_win,
263
            roundtrip_to=_LF_IN_REPO)
264
265
    def test_eol_native_clean_crlf(self):
266
        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='native')
267
        self.assertContent(wt, basis, _sample_text_on_unix,
268
            _sample_text_on_unix, _sample_text_on_win,
269
            roundtrip_to=_LF_IN_REPO)
270
271
    def test_eol_lf_clean_lf(self):
272
        wt, basis = self.prepare_tree(_sample_clean_lf, eol='lf')
273
        self.assertContent(wt, basis, _sample_text_on_unix,
274
            _sample_text_on_unix, _sample_text_on_win,
275
            roundtrip_to=_LF_IN_REPO)
276
277
    def test_eol_lf_clean_crlf(self):
278
        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='lf')
279
        self.assertContent(wt, basis, _sample_text_on_unix,
280
            _sample_text_on_unix, _sample_text_on_win,
281
            roundtrip_to=_LF_IN_REPO)
282
283
    def test_eol_crlf_clean_lf(self):
284
        wt, basis = self.prepare_tree(_sample_clean_lf, eol='crlf')
285
        self.assertContent(wt, basis, _sample_text_on_unix,
286
            _sample_text_on_unix, _sample_text_on_win,
287
            roundtrip_to=_LF_IN_REPO)
288
289
    def test_eol_crlf_clean_crlf(self):
290
        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='crlf')
291
        self.assertContent(wt, basis, _sample_text_on_unix,
292
            _sample_text_on_unix, _sample_text_on_win,
293
            roundtrip_to=_LF_IN_REPO)
294
295
    def test_eol_native_with_crlf_in_repo_clean_lf(self):
296
        wt, basis = self.prepare_tree(_sample_clean_lf,
297
            eol='native-with-crlf-in-repo')
298
        self.assertContent(wt, basis, _sample_text_on_win,
299
            _sample_text_on_unix, _sample_text_on_win,
300
            roundtrip_to=_CRLF_IN_REPO)
301
302
    def test_eol_native_with_crlf_in_repo_clean_crlf(self):
303
        wt, basis = self.prepare_tree(_sample_clean_crlf,
304
            eol='native-with-crlf-in-repo')
305
        self.assertContent(wt, basis, _sample_text_on_win,
306
            _sample_text_on_unix, _sample_text_on_win,
307
            roundtrip_to=_CRLF_IN_REPO)
308
309
    def test_eol_lf_with_crlf_in_repo_clean_lf(self):
310
        wt, basis = self.prepare_tree(_sample_clean_lf,
311
            eol='lf-with-crlf-in-repo')
312
        self.assertContent(wt, basis, _sample_text_on_win,
313
            _sample_text_on_unix, _sample_text_on_win,
314
            roundtrip_to=_CRLF_IN_REPO)
315
316
    def test_eol_lf_with_crlf_in_repo_clean_crlf(self):
317
        wt, basis = self.prepare_tree(_sample_clean_crlf,
318
            eol='lf-with-crlf-in-repo')
319
        self.assertContent(wt, basis, _sample_text_on_win,
320
            _sample_text_on_unix, _sample_text_on_win,
321
            roundtrip_to=_CRLF_IN_REPO)
322
323
    def test_eol_crlf_with_crlf_in_repo_clean_lf(self):
324
        wt, basis = self.prepare_tree(_sample_clean_lf,
325
            eol='crlf-with-crlf-in-repo')
326
        self.assertContent(wt, basis, _sample_text_on_win,
327
            _sample_text_on_unix, _sample_text_on_win,
328
            roundtrip_to=_CRLF_IN_REPO)
329
330
    def test_eol_crlf_with_crlf_in_repo_clean_crlf(self):
331
        wt, basis = self.prepare_tree(_sample_clean_crlf,
332
            eol='crlf-with-crlf-in-repo')
333
        self.assertContent(wt, basis, _sample_text_on_win,
334
            _sample_text_on_unix, _sample_text_on_win,
335
            roundtrip_to=_CRLF_IN_REPO)