1
# Copyright (C) 2009 Canonical Ltd
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for eol conversion."""
20
from cStringIO import StringIO
22
from bzrlib import rules, status
23
from bzrlib.tests import TestSkipped
24
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
25
from bzrlib.workingtree import WorkingTree
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"""
33
_sample_clean_lf = _sample_text_on_unix
34
_sample_clean_crlf = _sample_text_on_win
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]
42
class TestEolConversion(TestCaseWithWorkingTree):
45
# formats that don't support content filtering can skip these tests
46
fmt = self.workingtree_format
47
f = getattr(fmt, 'supports_content_filtering')
49
raise TestSkipped("format %s doesn't declare whether it "
50
"supports content filtering, assuming not" % fmt)
52
raise TestSkipped("format %s doesn't support content filtering"
54
TestCaseWithWorkingTree.setUp(self)
56
def patch_rules_searcher(self, eol):
57
"""Patch in a custom rules searcher with a given eol setting."""
59
WorkingTree._get_rules_searcher = self.real_rules_searcher
61
def custom_eol_rules_searcher(tree, default_searcher):
62
return rules._IniBasedRulesSearcher([
66
WorkingTree._get_rules_searcher = custom_eol_rules_searcher
68
def prepare_tree(self, content, eol=None):
69
"""Prepare a working tree and commit some content."""
70
self.real_rules_searcher = self.overrideAttr(
71
WorkingTree, '_get_rules_searcher')
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')
77
basis = t.basis_tree()
79
self.addCleanup(basis.unlock)
82
def assertNewContentForSetting(self, wt, eol, expected_unix,
83
expected_win, roundtrip):
84
"""Clone a working tree and check the convenience content.
86
If roundtrip is True, status and commit should see no changes.
88
if expected_win is None:
89
expected_win = expected_unix
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':
95
self.assertEqual(expected_win, content)
97
self.assertEqual(expected_unix, content)
98
# Confirm that status thinks nothing has changed if the text roundtrips
100
status_io = StringIO()
101
status.show_tree_status(wt2, to_file=status_io)
102
self.assertEqual('', status_io.getvalue())
104
def assertContent(self, wt, basis, expected_raw, expected_unix,
105
expected_win, roundtrip_to=None):
106
"""Check the committed content and content in cloned trees.
108
:param roundtrip_to: the set of formats (excluding exact) we
109
can round-trip to or None for all
111
basis_content = basis.get_file('file1-id').read()
112
self.assertEqual(expected_raw, basis_content)
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)
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
125
self.assertNewContentForSetting(wt, 'native',
126
expected_unix, expected_win, 'native' in roundtrip_to)
127
self.assertNewContentForSetting(wt, 'lf',
128
expected_unix, expected_unix, 'lf' in roundtrip_to)
129
self.assertNewContentForSetting(wt, 'crlf',
130
expected_win, expected_win, 'crlf' in roundtrip_to)
131
self.assertNewContentForSetting(wt, 'native-with-crlf-in-repo',
132
expected_unix, expected_win,
133
'native-with-crlf-in-repo' in roundtrip_to)
134
self.assertNewContentForSetting(wt, 'lf-with-crlf-in-repo',
135
expected_unix, expected_unix,
136
'lf-with-crlf-in-repo' in roundtrip_to)
137
self.assertNewContentForSetting(wt, 'crlf-with-crlf-in-repo',
138
expected_win, expected_win,
139
'crlf-with-crlf-in-repo' in roundtrip_to)
141
# Test binary files. These always roundtrip.
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,
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,
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,
158
def test_eol_lf_binary(self):
159
wt, basis = self.prepare_tree(_sample_binary, eol='lf')
160
self.assertContent(wt, basis, _sample_binary, _sample_binary,
163
def test_eol_crlf_binary(self):
164
wt, basis = self.prepare_tree(_sample_binary, eol='crlf')
165
self.assertContent(wt, basis, _sample_binary, _sample_binary,
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,
174
def test_eol_lf_with_crlf_in_repo_binary(self):
175
wt, basis = self.prepare_tree(_sample_binary,
176
eol='lf-with-crlf-in-repo')
177
self.assertContent(wt, basis, _sample_binary, _sample_binary,
180
def test_eol_crlf_with_crlf_in_repo_binary(self):
181
wt, basis = self.prepare_tree(_sample_binary,
182
eol='crlf-with-crlf-in-repo')
183
self.assertContent(wt, basis, _sample_binary, _sample_binary,
186
# Test text with mixed line endings ("dirty text").
187
# This doesn't roundtrip so status always thinks something has changed.
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=[])
194
def test_eol_exact_dirty(self):
195
wt, basis = self.prepare_tree(_sample_text, eol='exact')
196
self.assertContent(wt, basis, _sample_text,
197
_sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
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=[])
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=[])
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=[])
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=[])
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=[])
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=[])
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).
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)