/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.65.4 by James Westby
Make the rename handling more robust.
1
# Copyright (C) 2008 Canonical Ltd
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
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
import time
18
19
from bzrlib import (
20
    branch,
21
    tests,
22
    )
23
24
from bzrlib.plugins.fastimport import (
25
    commands,
26
    errors,
27
    )
28
29
from bzrlib.plugins.fastimport.processors import (
30
    generic_processor,
31
    )
32
33
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
34
class TestCaseForGenericProcessor(tests.TestCaseWithTransport):
0.65.4 by James Westby
Make the rename handling more robust.
35
36
    def get_handler(self):
37
        branch = self.make_branch('.')
38
        handler = generic_processor.GenericProcessor(branch.bzrdir)
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
39
        return handler, branch
0.65.4 by James Westby
Make the rename handling more robust.
40
41
    # FIXME: [] as a default is bad, as it is mutable, but I want
42
    # to use None to mean "don't check this".
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
43
    def assertChanges(self, branch, revno, expected_added=[],
44
            expected_removed=[], expected_modified=[],
0.80.3 by Ian Clatworthy
file <-> symlink change tests
45
            expected_renamed=[], expected_kind_changed=[]):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
46
        """Check the changes introduced in a revision of a branch.
47
48
        This method checks that a revision introduces expected changes.
49
        The required changes are passed in as a list, where
50
        each entry contains the needed information about the change.
51
52
        If you do not wish to assert anything about a particular
53
        category then pass None instead.
54
55
        branch: The branch.
56
        revno: revision number of revision to check.
57
        expected_added: a list of (filename,) tuples that must have
58
            been added in the delta.
59
        expected_removed: a list of (filename,) tuples that must have
60
            been removed in the delta.
61
        expected_modified: a list of (filename,) tuples that must have
62
            been modified in the delta.
63
        expected_renamed: a list of (old_path, new_path) tuples that
64
            must have been renamed in the delta.
0.80.3 by Ian Clatworthy
file <-> symlink change tests
65
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
66
            that must have been changed in the delta.
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
67
        :return: revtree1, revtree2
68
        """
69
        repo = branch.repository
0.80.1 by Ian Clatworthy
basic units tests for filemodify
70
        revtree1 = repo.revision_tree(branch.get_rev_id(revno - 1))
71
        revtree2 = repo.revision_tree(branch.get_rev_id(revno))
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
72
        changes = revtree2.changes_from(revtree1)
0.80.3 by Ian Clatworthy
file <-> symlink change tests
73
        self._check_changes(changes, expected_added, expected_removed,
74
            expected_modified, expected_renamed, expected_kind_changed)
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
75
        return revtree1, revtree2
76
0.80.3 by Ian Clatworthy
file <-> symlink change tests
77
    def _check_changes(self, changes, expected_added=[],
0.65.4 by James Westby
Make the rename handling more robust.
78
            expected_removed=[], expected_modified=[],
0.80.3 by Ian Clatworthy
file <-> symlink change tests
79
            expected_renamed=[], expected_kind_changed=[]):
0.65.4 by James Westby
Make the rename handling more robust.
80
        """Check the changes in a TreeDelta
81
82
        This method checks that the TreeDelta contains the expected
83
        modifications between the two trees that were used to generate
84
        it. The required changes are passed in as a list, where
85
        each entry contains the needed information about the change.
86
87
        If you do not wish to assert anything about a particular
88
        category then pass None instead.
89
90
        changes: The TreeDelta to check.
91
        expected_added: a list of (filename,) tuples that must have
92
            been added in the delta.
93
        expected_removed: a list of (filename,) tuples that must have
94
            been removed in the delta.
95
        expected_modified: a list of (filename,) tuples that must have
96
            been modified in the delta.
97
        expected_renamed: a list of (old_path, new_path) tuples that
98
            must have been renamed in the delta.
0.80.3 by Ian Clatworthy
file <-> symlink change tests
99
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
100
            that must have been changed in the delta.
0.65.4 by James Westby
Make the rename handling more robust.
101
        """
102
        renamed = changes.renamed
103
        added = changes.added
104
        removed = changes.removed
105
        modified = changes.modified
0.80.3 by Ian Clatworthy
file <-> symlink change tests
106
        kind_changed = changes.kind_changed
0.65.4 by James Westby
Make the rename handling more robust.
107
        if expected_renamed is not None:
108
            self.assertEquals(len(renamed), len(expected_renamed),
0.74.1 by John Arbash Meinel
Change the rename code to create a new text entry.
109
                "%s is renamed, expected %s" % (renamed, expected_renamed))
0.65.4 by James Westby
Make the rename handling more robust.
110
            renamed_files = [(item[0], item[1]) for item in renamed]
111
            for expected_renamed_entry in expected_renamed:
112
                self.assertTrue(expected_renamed_entry in renamed_files,
113
                    "%s is not renamed, %s are" % (str(expected_renamed_entry),
114
                        renamed_files))
115
        if expected_added is not None:
116
            self.assertEquals(len(added), len(expected_added),
117
                "%s is added" % str(added))
118
            added_files = [(item[0],) for item in added]
119
            for expected_added_entry in expected_added:
120
                self.assertTrue(expected_added_entry in added_files,
121
                    "%s is not added, %s are" % (str(expected_added_entry),
122
                        added_files))
123
        if expected_removed is not None:
124
            self.assertEquals(len(removed), len(expected_removed),
125
                "%s is removed" % str(removed))
126
            removed_files = [(item[0],) for item in removed]
127
            for expected_removed_entry in expected_removed:
128
                self.assertTrue(expected_removed_entry in removed_files,
129
                    "%s is not removed, %s are" % (str(expected_removed_entry),
130
                        removed_files))
131
        if expected_modified is not None:
132
            self.assertEquals(len(modified), len(expected_modified),
133
                "%s is modified" % str(modified))
134
            modified_files = [(item[0],) for item in modified]
135
            for expected_modified_entry in expected_modified:
136
                self.assertTrue(expected_modified_entry in modified_files,
0.80.3 by Ian Clatworthy
file <-> symlink change tests
137
                    "%s is not modified, %s are" % (
138
                    str(expected_modified_entry), modified_files))
139
        if expected_kind_changed is not None:
140
            self.assertEquals(len(kind_changed), len(expected_kind_changed),
141
                "%s is kind-changed, expected %s" % (kind_changed,
142
                    expected_kind_changed))
143
            kind_changed_files = [(item[0], item[2], item[3])
144
                for item in kind_changed]
145
            for expected_kind_changed_entry in expected_kind_changed:
146
                self.assertTrue(expected_kind_changed_entry in
147
                    kind_changed_files, "%s is not kind-changed, %s are" % (
148
                    str(expected_kind_changed_entry), kind_changed_files))
0.65.4 by James Westby
Make the rename handling more robust.
149
0.80.1 by Ian Clatworthy
basic units tests for filemodify
150
    def assertContent(self, branch, tree, path, content):
151
        file_id = tree.inventory.path2id(path)
152
        branch.lock_read()
153
        self.addCleanup(branch.unlock)
154
        self.assertEqual(tree.get_file_text(file_id), content)
155
156
    def assertSymlinkTarget(self, branch, tree, path, target):
157
        file_id = tree.inventory.path2id(path)
158
        branch.lock_read()
159
        self.addCleanup(branch.unlock)
160
        self.assertEqual(tree.get_symlink_target(file_id), target)
161
0.80.4 by Ian Clatworthy
file executable off <-> on tests
162
    def assertExecutable(self, branch, tree, path, executable):
163
        file_id = tree.inventory.path2id(path)
164
        branch.lock_read()
165
        self.addCleanup(branch.unlock)
166
        self.assertEqual(tree.is_executable(file_id), executable)
167
0.80.1 by Ian Clatworthy
basic units tests for filemodify
168
    def assertRevisionRoot(self, revtree, path):
169
        self.assertEqual(revtree.get_revision_id(),
170
                         revtree.inventory.root.children[path].revision)
171
172
173
class TestModify(TestCaseForGenericProcessor):
174
0.80.3 by Ian Clatworthy
file <-> symlink change tests
175
    def file_command_iter(self, path, kind='file', content='aaa',
0.80.4 by Ian Clatworthy
file executable off <-> on tests
176
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
177
        # Revno 1: create a file or symlink
178
        # Revno 2: modify it
0.80.3 by Ian Clatworthy
file <-> symlink change tests
179
        if to_kind is None:
180
            to_kind = kind
0.80.4 by Ian Clatworthy
file executable off <-> on tests
181
        if to_executable is None:
182
            to_executable = executable
0.80.1 by Ian Clatworthy
basic units tests for filemodify
183
        def command_list():
184
            author = ['', 'bugs@a.com', time.time(), time.timezone]
185
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
186
            def files_one():
0.80.4 by Ian Clatworthy
file executable off <-> on tests
187
                yield commands.FileModifyCommand(path, kind, executable,
0.80.3 by Ian Clatworthy
file <-> symlink change tests
188
                        None, content)
0.80.1 by Ian Clatworthy
basic units tests for filemodify
189
            yield commands.CommitCommand('head', '1', author,
190
                committer, "commit 1", None, [], files_one)
191
            def files_two():
0.80.4 by Ian Clatworthy
file executable off <-> on tests
192
                yield commands.FileModifyCommand(path, to_kind, to_executable,
0.80.3 by Ian Clatworthy
file <-> symlink change tests
193
                        None, to_content)
0.80.1 by Ian Clatworthy
basic units tests for filemodify
194
            yield commands.CommitCommand('head', '2', author,
195
                committer, "commit 2", ":1", [], files_two)
196
        return command_list
197
198
    def test_modify_file_in_root(self):
199
        handler, branch = self.get_handler()
200
        path = 'a'
201
        handler.process(self.file_command_iter(path))
202
        revtree0, revtree1 = self.assertChanges(branch, 1,
203
            expected_added=[(path,)])
204
        revtree1, revtree2 = self.assertChanges(branch, 2,
205
            expected_modified=[(path,)])
206
        self.assertContent(branch, revtree1, path, "aaa")
207
        self.assertContent(branch, revtree2, path, "bbb")
208
        self.assertRevisionRoot(revtree1, path)
209
        self.assertRevisionRoot(revtree2, path)
210
211
    def test_modify_file_in_subdir(self):
212
        handler, branch = self.get_handler()
213
        path = 'a/a'
214
        handler.process(self.file_command_iter(path))
215
        revtree0, revtree1 = self.assertChanges(branch, 1,
216
            expected_added=[('a',), (path,)])
217
        revtree1, revtree2 = self.assertChanges(branch, 2,
218
            expected_modified=[(path,)])
219
        self.assertContent(branch, revtree1, path, "aaa")
220
        self.assertContent(branch, revtree2, path, "bbb")
221
222
    def test_modify_symlink_in_root(self):
223
        handler, branch = self.get_handler()
224
        path = 'a'
225
        handler.process(self.file_command_iter(path, kind='symlink'))
226
        revtree1, revtree2 = self.assertChanges(branch, 2,
227
            expected_modified=[(path,)])
228
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
229
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
230
        self.assertRevisionRoot(revtree1, path)
231
        self.assertRevisionRoot(revtree2, path)
232
233
    def test_modify_symlink_in_subdir(self):
234
        handler, branch = self.get_handler()
235
        path = 'a/a'
236
        handler.process(self.file_command_iter(path, kind='symlink'))
237
        revtree0, revtree1 = self.assertChanges(branch, 1,
238
            expected_added=[('a',), (path,)])
239
        revtree1, revtree2 = self.assertChanges(branch, 2,
240
            expected_modified=[(path,)])
241
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
242
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
243
0.80.3 by Ian Clatworthy
file <-> symlink change tests
244
    def test_modify_file_becomes_symlink(self):
245
        handler, branch = self.get_handler()
246
        path = 'a/a'
247
        handler.process(self.file_command_iter(path,
248
            kind='file', to_kind='symlink'))
249
        revtree0, revtree1 = self.assertChanges(branch, 1,
250
            expected_added=[('a',), (path,)])
251
        revtree1, revtree2 = self.assertChanges(branch, 2,
252
            expected_kind_changed=[(path, 'file', 'symlink')])
253
        self.assertContent(branch, revtree1, path, "aaa")
254
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
255
256
    def test_modify_symlink_becomes_file(self):
257
        handler, branch = self.get_handler()
258
        path = 'a/a'
259
        handler.process(self.file_command_iter(path,
260
            kind='symlink', to_kind='file'))
261
        revtree0, revtree1 = self.assertChanges(branch, 1,
262
            expected_added=[('a',), (path,)])
263
        revtree1, revtree2 = self.assertChanges(branch, 2,
264
            expected_kind_changed=[(path, 'symlink', 'file')])
265
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
266
        self.assertContent(branch, revtree2, path, "bbb")
267
0.80.4 by Ian Clatworthy
file executable off <-> on tests
268
    def test_modify_file_now_executable(self):
269
        handler, branch = self.get_handler()
270
        path = 'a/a'
271
        handler.process(self.file_command_iter(path,
272
            executable=False, to_executable=True, to_content='aaa'))
273
        revtree0, revtree1 = self.assertChanges(branch, 1,
274
            expected_added=[('a',), (path,)])
275
        revtree1, revtree2 = self.assertChanges(branch, 2,
276
            expected_modified=[(path,)])
277
        self.assertExecutable(branch, revtree1, path, False)
278
        self.assertExecutable(branch, revtree2, path, True)
279
280
    def test_modify_file_no_longer_executable(self):
281
        handler, branch = self.get_handler()
282
        path = 'a/a'
283
        handler.process(self.file_command_iter(path,
284
            executable=True, to_executable=False, to_content='aaa'))
285
        revtree0, revtree1 = self.assertChanges(branch, 1,
286
            expected_added=[('a',), (path,)])
287
        revtree1, revtree2 = self.assertChanges(branch, 2,
288
            expected_modified=[(path,)])
289
        self.assertExecutable(branch, revtree1, path, True)
290
        self.assertExecutable(branch, revtree2, path, False)
291
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
292
0.80.5 by Ian Clatworthy
file/symlink <-> directory change tests & fix
293
class TestModifyTricky(TestCaseForGenericProcessor):
294
295
    def file_command_iter(self, path1, path2, kind='file'):
296
        # Revno 1: create a file or symlink in a directory
297
        # Revno 2: create a second file that implicitly deletes the
298
        # first one because either:
299
        # * the new file is a in directory with the old file name
300
        # * the new file has the same name as the directory of the first
301
        def command_list():
302
            author = ['', 'bugs@a.com', time.time(), time.timezone]
303
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
304
            def files_one():
305
                yield commands.FileModifyCommand(path1, kind, False,
306
                        None, "aaa")
307
            yield commands.CommitCommand('head', '1', author,
308
                committer, "commit 1", None, [], files_one)
309
            def files_two():
310
                yield commands.FileModifyCommand(path2, kind, False,
311
                        None, "bbb")
312
            yield commands.CommitCommand('head', '2', author,
313
                committer, "commit 2", ":1", [], files_two)
314
        return command_list
315
316
317
    def test_modify_file_becomes_directory(self):
318
        handler, branch = self.get_handler()
319
        path1 = 'a/b'
320
        path2 = 'a/b/c'
321
        handler.process(self.file_command_iter(path1, path2))
322
        revtree0, revtree1 = self.assertChanges(branch, 1,
323
            expected_added=[('a',), (path1,)])
324
        revtree1, revtree2 = self.assertChanges(branch, 2,
325
            expected_added=[(path2,)],
326
            expected_kind_changed=[(path1, 'file', 'directory')])
327
        self.assertContent(branch, revtree1, path1, "aaa")
328
        self.assertContent(branch, revtree2, path2, "bbb")
329
330
    def test_modify_directory_becomes_file(self):
331
        handler, branch = self.get_handler()
332
        path1 = 'a/b/c'
333
        path2 = 'a/b'
334
        handler.process(self.file_command_iter(path1, path2))
335
        revtree0, revtree1 = self.assertChanges(branch, 1,
336
            expected_added=[('a',), ('a/b',), (path1,)])
337
        revtree1, revtree2 = self.assertChanges(branch, 2,
338
            expected_removed=[(path1,),],
339
            expected_kind_changed=[(path2, 'directory', 'file')])
340
        self.assertContent(branch, revtree1, path1, "aaa")
341
        self.assertContent(branch, revtree2, path2, "bbb")
342
343
    def test_modify_symlink_becomes_directory(self):
344
        handler, branch = self.get_handler()
345
        path1 = 'a/b'
346
        path2 = 'a/b/c'
347
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
348
        revtree0, revtree1 = self.assertChanges(branch, 1,
349
            expected_added=[('a',), (path1,)])
350
        revtree1, revtree2 = self.assertChanges(branch, 2,
351
            expected_added=[(path2,)],
352
            expected_kind_changed=[(path1, 'symlink', 'directory')])
353
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
354
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
355
356
    def test_modify_directory_becomes_symlink(self):
357
        handler, branch = self.get_handler()
358
        path1 = 'a/b/c'
359
        path2 = 'a/b'
360
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
361
        revtree0, revtree1 = self.assertChanges(branch, 1,
362
            expected_added=[('a',), ('a/b',), (path1,)])
363
        revtree1, revtree2 = self.assertChanges(branch, 2,
364
            expected_removed=[(path1,),],
365
            expected_kind_changed=[(path2, 'directory', 'symlink')])
366
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
367
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
368
369
0.80.2 by Ian Clatworthy
basic delete tests
370
class TestDelete(TestCaseForGenericProcessor):
371
372
    def file_command_iter(self, path, kind='file'):
0.80.4 by Ian Clatworthy
file executable off <-> on tests
373
        # Revno 1: create a file or symlink
374
        # Revno 2: delete it
0.80.2 by Ian Clatworthy
basic delete tests
375
        def command_list():
376
            author = ['', 'bugs@a.com', time.time(), time.timezone]
377
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
378
            def files_one():
379
                yield commands.FileModifyCommand(path, kind, False,
380
                        None, "aaa")
381
            yield commands.CommitCommand('head', '1', author,
382
                committer, "commit 1", None, [], files_one)
383
            def files_two():
384
                yield commands.FileDeleteCommand(path)
385
            yield commands.CommitCommand('head', '2', author,
386
                committer, "commit 2", ":1", [], files_two)
387
        return command_list
388
389
    def test_delete_file_in_root(self):
390
        handler, branch = self.get_handler()
391
        path = 'a'
392
        handler.process(self.file_command_iter(path))
393
        revtree0, revtree1 = self.assertChanges(branch, 1,
394
            expected_added=[(path,)])
395
        revtree1, revtree2 = self.assertChanges(branch, 2,
396
            expected_removed=[(path,)])
397
        self.assertContent(branch, revtree1, path, "aaa")
398
        self.assertRevisionRoot(revtree1, path)
399
400
    def test_delete_file_in_subdir(self):
401
        handler, branch = self.get_handler()
402
        path = 'a/a'
403
        handler.process(self.file_command_iter(path))
404
        revtree0, revtree1 = self.assertChanges(branch, 1,
405
            expected_added=[('a',), (path,)])
406
        revtree1, revtree2 = self.assertChanges(branch, 2,
407
            expected_removed=[(path,)])
408
        self.assertContent(branch, revtree1, path, "aaa")
409
410
    def test_delete_symlink_in_root(self):
411
        handler, branch = self.get_handler()
412
        path = 'a'
413
        handler.process(self.file_command_iter(path, kind='symlink'))
414
        revtree1, revtree2 = self.assertChanges(branch, 2,
415
            expected_removed=[(path,)])
416
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
417
        self.assertRevisionRoot(revtree1, path)
418
419
    def test_delete_symlink_in_subdir(self):
420
        handler, branch = self.get_handler()
421
        path = 'a/a'
422
        handler.process(self.file_command_iter(path, kind='symlink'))
423
        revtree0, revtree1 = self.assertChanges(branch, 1,
424
            expected_added=[('a',), (path,)])
425
        revtree1, revtree2 = self.assertChanges(branch, 2,
426
            expected_removed=[(path,)])
427
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
428
429
0.80.7 by Ian Clatworthy
add directory delete test
430
class TestDeleteDirectory(TestCaseForGenericProcessor):
431
432
    def file_command_iter(self, paths, dir):
433
        # Revno 1: create multiple files
434
        # Revno 2: delete a directory holding those files
435
        def command_list():
436
            author = ['', 'bugs@a.com', time.time(), time.timezone]
437
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
438
            def files_one():
439
                for i, path in enumerate(paths):
440
                    yield commands.FileModifyCommand(path, 'file', False,
441
                            None, "aaa%d" % i)
442
            yield commands.CommitCommand('head', '1', author,
443
                committer, "commit 1", None, [], files_one)
444
            def files_two():
445
                yield commands.FileDeleteCommand(dir)
446
            yield commands.CommitCommand('head', '2', author,
447
                committer, "commit 2", ":1", [], files_two)
448
        return command_list
449
450
    def test_delete_dir(self):
451
        handler, branch = self.get_handler()
452
        paths = ['a/b/c', 'a/b/d', 'a/b/e/f', 'a/g']
453
        dir = 'a/b'
454
        handler.process(self.file_command_iter(paths, dir))
455
        revtree0, revtree1 = self.assertChanges(branch, 1,
456
            expected_added=[
457
                ('a',), ('a/b',), ('a/b/c',),
458
                ('a/b/d',),
459
                ('a/b/e',), ('a/b/e/f',),
460
                ('a/g',),
461
                ])
462
        revtree1, revtree2 = self.assertChanges(branch, 2,
463
            expected_removed=[
464
                ('a/b',), ('a/b/c',),
465
                ('a/b/d',),
466
                ('a/b/e',), ('a/b/e/f',),
467
                ])
468
469
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
470
class TestRename(TestCaseForGenericProcessor):
471
472
    def get_command_iter(self, old_path, new_path):
0.80.4 by Ian Clatworthy
file executable off <-> on tests
473
        # Revno 1: create a file or symlink
474
        # Revno 2: rename it
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
475
        def command_list():
476
            author = ['', 'bugs@a.com', time.time(), time.timezone]
477
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
478
            def files_one():
479
                yield commands.FileModifyCommand(old_path, 'file', False,
480
                        None, "aaa")
481
            yield commands.CommitCommand('head', '1', author,
482
                committer, "commit 1", None, [], files_one)
483
            def files_two():
484
                yield commands.FileRenameCommand(old_path, new_path)
485
            yield commands.CommitCommand('head', '2', author,
486
                committer, "commit 2", ":1", [], files_two)
487
        return command_list
488
0.65.4 by James Westby
Make the rename handling more robust.
489
    def test_rename_in_root(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
490
        handler, branch = self.get_handler()
0.65.4 by James Westby
Make the rename handling more robust.
491
        old_path = 'a'
492
        new_path = 'b'
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
493
        handler.process(self.get_command_iter(old_path, new_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
494
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
495
            expected_renamed=[(old_path, new_path)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
496
        self.assertRevisionRoot(revtree1, old_path)
497
        self.assertRevisionRoot(revtree2, new_path)
0.65.4 by James Westby
Make the rename handling more robust.
498
499
    def test_rename_in_subdir(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
500
        handler, branch = self.get_handler()
0.65.4 by James Westby
Make the rename handling more robust.
501
        old_path = 'a/a'
502
        new_path = 'a/b'
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
503
        handler.process(self.get_command_iter(old_path, new_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
504
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)])
0.65.4 by James Westby
Make the rename handling more robust.
505
506
    def test_move_to_new_dir(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
507
        handler, branch = self.get_handler()
0.65.4 by James Westby
Make the rename handling more robust.
508
        old_path = 'a/a'
509
        new_path = 'b/a'
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
510
        handler.process(self.get_command_iter(old_path, new_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
511
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)],
0.65.4 by James Westby
Make the rename handling more robust.
512
            expected_added=[('b',)])
0.64.74 by Ian Clatworthy
fix symlink importing
513
514
0.80.6 by Ian Clatworthy
file/symlink <-> directory rename tests
515
class TestRenameTricky(TestCaseForGenericProcessor):
516
517
    def file_command_iter(self, path1, old_path2, new_path2, kind='file'):
518
        # Revno 1: create two files or symlinks in a directory
519
        # Revno 2: rename the second file so that it implicitly deletes the
520
        # first one because either:
521
        # * the new file is a in directory with the old file name
522
        # * the new file has the same name as the directory of the first
523
        def command_list():
524
            author = ['', 'bugs@a.com', time.time(), time.timezone]
525
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
526
            def files_one():
527
                yield commands.FileModifyCommand(path1, kind, False,
528
                        None, "aaa")
529
                yield commands.FileModifyCommand(old_path2, kind, False,
530
                        None, "bbb")
531
            yield commands.CommitCommand('head', '1', author,
532
                committer, "commit 1", None, [], files_one)
533
            def files_two():
534
                yield commands.FileRenameCommand(old_path2, new_path2)
535
            yield commands.CommitCommand('head', '2', author,
536
                committer, "commit 2", ":1", [], files_two)
537
        return command_list
538
539
540
    def test_rename_file_becomes_directory(self):
541
        handler, branch = self.get_handler()
542
        old_path2 = 'foo'
543
        path1     = 'a/b'
544
        new_path2 = 'a/b/c'
545
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
546
        revtree0, revtree1 = self.assertChanges(branch, 1,
547
            expected_added=[('a',), (path1,), (old_path2,)])
548
        revtree1, revtree2 = self.assertChanges(branch, 2,
549
            expected_renamed=[(old_path2, new_path2)],
550
            expected_kind_changed=[(path1, 'file', 'directory')])
551
        self.assertContent(branch, revtree1, path1, "aaa")
552
        self.assertContent(branch, revtree2, new_path2, "bbb")
553
554
    def test_rename_directory_becomes_file(self):
555
        handler, branch = self.get_handler()
556
        old_path2 = 'foo'
557
        path1     = 'a/b/c'
558
        new_path2 = 'a/b'
559
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
560
        revtree0, revtree1 = self.assertChanges(branch, 1,
561
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
562
        revtree1, revtree2 = self.assertChanges(branch, 2,
563
            expected_renamed=[(old_path2, new_path2)],
564
            expected_removed=[(path1,), (new_path2,)])
565
        self.assertContent(branch, revtree1, path1, "aaa")
566
        self.assertContent(branch, revtree2, new_path2, "bbb")
567
568
    def test_rename_symlink_becomes_directory(self):
569
        handler, branch = self.get_handler()
570
        old_path2 = 'foo'
571
        path1     = 'a/b'
572
        new_path2 = 'a/b/c'
573
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
574
            'symlink'))
575
        revtree0, revtree1 = self.assertChanges(branch, 1,
576
            expected_added=[('a',), (path1,), (old_path2,)])
577
        revtree1, revtree2 = self.assertChanges(branch, 2,
578
            expected_renamed=[(old_path2, new_path2)],
579
            expected_kind_changed=[(path1, 'symlink', 'directory')])
580
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
581
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
582
583
    def test_rename_directory_becomes_symlink(self):
584
        handler, branch = self.get_handler()
585
        old_path2 = 'foo'
586
        path1     = 'a/b/c'
587
        new_path2 = 'a/b'
588
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
589
            'symlink'))
590
        revtree0, revtree1 = self.assertChanges(branch, 1,
591
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
592
        revtree1, revtree2 = self.assertChanges(branch, 2,
593
            expected_renamed=[(old_path2, new_path2)],
594
            expected_removed=[(path1,), (new_path2,)])
595
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
596
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
597
598
0.76.2 by Ian Clatworthy
code & tests for file copying
599
class TestCopy(TestCaseForGenericProcessor):
600
0.80.1 by Ian Clatworthy
basic units tests for filemodify
601
    def file_command_iter(self, src_path, dest_path, kind='file'):
0.80.4 by Ian Clatworthy
file executable off <-> on tests
602
        # Revno 1: create a file or symlink
603
        # Revno 2: copy it
0.76.2 by Ian Clatworthy
code & tests for file copying
604
        def command_list():
605
            author = ['', 'bugs@a.com', time.time(), time.timezone]
606
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
607
            def files_one():
0.80.1 by Ian Clatworthy
basic units tests for filemodify
608
                yield commands.FileModifyCommand(src_path, kind, False,
0.76.2 by Ian Clatworthy
code & tests for file copying
609
                        None, "aaa")
610
            yield commands.CommitCommand('head', '1', author,
611
                committer, "commit 1", None, [], files_one)
612
            def files_two():
613
                yield commands.FileCopyCommand(src_path, dest_path)
614
            yield commands.CommitCommand('head', '2', author,
615
                committer, "commit 2", ":1", [], files_two)
616
        return command_list
617
618
    def test_copy_file_in_root(self):
619
        handler, branch = self.get_handler()
620
        src_path = 'a'
621
        dest_path = 'b'
622
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
623
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
624
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
625
        self.assertContent(branch, revtree1, src_path, "aaa")
626
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
627
        self.assertContent(branch, revtree2, dest_path, "aaa")
0.80.1 by Ian Clatworthy
basic units tests for filemodify
628
        self.assertRevisionRoot(revtree1, src_path)
629
        self.assertRevisionRoot(revtree2, dest_path)
0.76.2 by Ian Clatworthy
code & tests for file copying
630
631
    def test_copy_file_in_subdir(self):
632
        handler, branch = self.get_handler()
633
        src_path = 'a/a'
634
        dest_path = 'a/b'
635
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
636
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
637
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
638
        self.assertContent(branch, revtree1, src_path, "aaa")
639
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
640
        self.assertContent(branch, revtree2, dest_path, "aaa")
641
642
    def test_copy_file_to_new_dir(self):
643
        handler, branch = self.get_handler()
644
        src_path = 'a/a'
645
        dest_path = 'b/a'
646
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
647
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
648
            expected_added=[('b',), (dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
649
        self.assertContent(branch, revtree1, src_path, "aaa")
650
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
651
        self.assertContent(branch, revtree2, dest_path, "aaa")
652
0.76.3 by Ian Clatworthy
symlink copying tests
653
    def test_copy_symlink_in_root(self):
654
        handler, branch = self.get_handler()
655
        src_path = 'a'
656
        dest_path = 'b'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
657
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
658
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
659
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
660
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
661
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
662
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
0.80.1 by Ian Clatworthy
basic units tests for filemodify
663
        self.assertRevisionRoot(revtree1, src_path)
664
        self.assertRevisionRoot(revtree2, dest_path)
0.76.3 by Ian Clatworthy
symlink copying tests
665
666
    def test_copy_symlink_in_subdir(self):
667
        handler, branch = self.get_handler()
668
        src_path = 'a/a'
669
        dest_path = 'a/b'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
670
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
671
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
672
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
673
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
674
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
675
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
676
677
    def test_copy_symlink_to_new_dir(self):
678
        handler, branch = self.get_handler()
679
        src_path = 'a/a'
680
        dest_path = 'b/a'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
681
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
682
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
683
            expected_added=[('b',), (dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
684
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
685
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
686
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
687
0.76.2 by Ian Clatworthy
code & tests for file copying
688
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
689
class TestFileKinds(TestCaseForGenericProcessor):
0.64.74 by Ian Clatworthy
fix symlink importing
690
691
    def get_command_iter(self, path, kind, content):
692
        def command_list():
693
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
694
            def files_one():
695
                yield commands.FileModifyCommand(path, kind, False,
696
                        None, content)
697
            yield commands.CommitCommand('head', '1', None,
698
                committer, "commit 1", None, [], files_one)
699
        return command_list
700
701
    def test_import_plainfile(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
702
        handler, branch = self.get_handler()
703
        handler.process(self.get_command_iter('foo', 'file', 'aaa'))
0.64.74 by Ian Clatworthy
fix symlink importing
704
705
    def test_import_symlink(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
706
        handler, branch = self.get_handler()
707
        handler.process(self.get_command_iter('foo', 'symlink', 'bar'))