/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
0.64.334 by Jelmer Vernooij
Remove old FSF address. Thanks Dan Callaghan.
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
0.65.4 by James Westby
Make the rename handling more robust.
15
16
import time
17
18
from bzrlib import (
19
    tests,
20
    )
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
21
from bzrlib.plugins.fastimport.helpers import (
22
    kind_to_mode,
23
    )
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
24
from bzrlib.plugins.fastimport.tests import (
25
    FastimportFeature,
0.65.4 by James Westby
Make the rename handling more robust.
26
    )
27
0.123.14 by Jelmer Vernooij
Simplify imports in case fastimport is not installed.
28
try:
29
    from fastimport import commands
30
except ImportError:
31
    commands = object()
32
0.65.4 by James Westby
Make the rename handling more robust.
33
0.115.2 by John Arbash Meinel
Change to multiplying tests rather than manually.
34
def load_tests(standard_tests, module, loader):
35
    """Parameterize tests for all versions of groupcompress."""
36
    scenarios = [
37
        ('pack-0.92', {'branch_format': 'pack-0.92'}),
38
        ('1.9-rich-root', {'branch_format': '1.9-rich-root'}),
39
    ]
40
    try:
41
        from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
42
        scenarios.append(('2a', {'branch_format': '2a'}))
43
    except ImportError:
44
        pass
45
    suite = loader.suiteClass()
46
    result = tests.multiply_tests(standard_tests, scenarios, suite)
47
    return result
48
49
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
50
class TestCaseForGenericProcessor(tests.TestCaseWithTransport):
0.65.4 by James Westby
Make the rename handling more robust.
51
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
52
    _test_needs_features = [FastimportFeature]
53
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
54
    branch_format = "pack-0.92"
55
0.65.4 by James Westby
Make the rename handling more robust.
56
    def get_handler(self):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
57
        from bzrlib.plugins.fastimport.processors import (
58
            generic_processor,
59
            )
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
60
        branch = self.make_branch('.', format=self.branch_format)
0.96.1 by Ian Clatworthy
update existing tests to reflect implicit directory pruning bahaviour
61
        handler = generic_processor.GenericProcessor(branch.bzrdir)
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
62
        return handler, branch
0.65.4 by James Westby
Make the rename handling more robust.
63
64
    # FIXME: [] as a default is bad, as it is mutable, but I want
65
    # to use None to mean "don't check this".
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
66
    def assertChanges(self, branch, revno, expected_added=[],
67
            expected_removed=[], expected_modified=[],
0.80.3 by Ian Clatworthy
file <-> symlink change tests
68
            expected_renamed=[], expected_kind_changed=[]):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
69
        """Check the changes introduced in a revision of a branch.
70
71
        This method checks that a revision introduces expected changes.
72
        The required changes are passed in as a list, where
73
        each entry contains the needed information about the change.
74
75
        If you do not wish to assert anything about a particular
76
        category then pass None instead.
77
78
        branch: The branch.
79
        revno: revision number of revision to check.
80
        expected_added: a list of (filename,) tuples that must have
81
            been added in the delta.
82
        expected_removed: a list of (filename,) tuples that must have
83
            been removed in the delta.
84
        expected_modified: a list of (filename,) tuples that must have
85
            been modified in the delta.
86
        expected_renamed: a list of (old_path, new_path) tuples that
87
            must have been renamed in the delta.
0.80.3 by Ian Clatworthy
file <-> symlink change tests
88
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
89
            that must have been changed in the delta.
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
90
        :return: revtree1, revtree2
91
        """
92
        repo = branch.repository
0.80.1 by Ian Clatworthy
basic units tests for filemodify
93
        revtree1 = repo.revision_tree(branch.get_rev_id(revno - 1))
94
        revtree2 = repo.revision_tree(branch.get_rev_id(revno))
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
95
        changes = revtree2.changes_from(revtree1)
0.80.3 by Ian Clatworthy
file <-> symlink change tests
96
        self._check_changes(changes, expected_added, expected_removed,
97
            expected_modified, expected_renamed, expected_kind_changed)
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
98
        return revtree1, revtree2
99
0.80.3 by Ian Clatworthy
file <-> symlink change tests
100
    def _check_changes(self, changes, expected_added=[],
0.65.4 by James Westby
Make the rename handling more robust.
101
            expected_removed=[], expected_modified=[],
0.80.3 by Ian Clatworthy
file <-> symlink change tests
102
            expected_renamed=[], expected_kind_changed=[]):
0.65.4 by James Westby
Make the rename handling more robust.
103
        """Check the changes in a TreeDelta
104
105
        This method checks that the TreeDelta contains the expected
106
        modifications between the two trees that were used to generate
107
        it. The required changes are passed in as a list, where
108
        each entry contains the needed information about the change.
109
110
        If you do not wish to assert anything about a particular
111
        category then pass None instead.
112
113
        changes: The TreeDelta to check.
114
        expected_added: a list of (filename,) tuples that must have
115
            been added in the delta.
116
        expected_removed: a list of (filename,) tuples that must have
117
            been removed in the delta.
118
        expected_modified: a list of (filename,) tuples that must have
119
            been modified in the delta.
120
        expected_renamed: a list of (old_path, new_path) tuples that
121
            must have been renamed in the delta.
0.80.3 by Ian Clatworthy
file <-> symlink change tests
122
        expected_kind_changed: a list of (path, old_kind, new_kind) tuples
123
            that must have been changed in the delta.
0.65.4 by James Westby
Make the rename handling more robust.
124
        """
125
        renamed = changes.renamed
126
        added = changes.added
127
        removed = changes.removed
128
        modified = changes.modified
0.80.3 by Ian Clatworthy
file <-> symlink change tests
129
        kind_changed = changes.kind_changed
0.65.4 by James Westby
Make the rename handling more robust.
130
        if expected_renamed is not None:
131
            self.assertEquals(len(renamed), len(expected_renamed),
0.74.1 by John Arbash Meinel
Change the rename code to create a new text entry.
132
                "%s is renamed, expected %s" % (renamed, expected_renamed))
0.65.4 by James Westby
Make the rename handling more robust.
133
            renamed_files = [(item[0], item[1]) for item in renamed]
134
            for expected_renamed_entry in expected_renamed:
135
                self.assertTrue(expected_renamed_entry in renamed_files,
136
                    "%s is not renamed, %s are" % (str(expected_renamed_entry),
137
                        renamed_files))
138
        if expected_added is not None:
139
            self.assertEquals(len(added), len(expected_added),
140
                "%s is added" % str(added))
141
            added_files = [(item[0],) for item in added]
142
            for expected_added_entry in expected_added:
143
                self.assertTrue(expected_added_entry in added_files,
144
                    "%s is not added, %s are" % (str(expected_added_entry),
145
                        added_files))
146
        if expected_removed is not None:
147
            self.assertEquals(len(removed), len(expected_removed),
148
                "%s is removed" % str(removed))
149
            removed_files = [(item[0],) for item in removed]
150
            for expected_removed_entry in expected_removed:
151
                self.assertTrue(expected_removed_entry in removed_files,
152
                    "%s is not removed, %s are" % (str(expected_removed_entry),
153
                        removed_files))
154
        if expected_modified is not None:
155
            self.assertEquals(len(modified), len(expected_modified),
156
                "%s is modified" % str(modified))
157
            modified_files = [(item[0],) for item in modified]
158
            for expected_modified_entry in expected_modified:
159
                self.assertTrue(expected_modified_entry in modified_files,
0.80.3 by Ian Clatworthy
file <-> symlink change tests
160
                    "%s is not modified, %s are" % (
161
                    str(expected_modified_entry), modified_files))
162
        if expected_kind_changed is not None:
163
            self.assertEquals(len(kind_changed), len(expected_kind_changed),
164
                "%s is kind-changed, expected %s" % (kind_changed,
165
                    expected_kind_changed))
166
            kind_changed_files = [(item[0], item[2], item[3])
167
                for item in kind_changed]
168
            for expected_kind_changed_entry in expected_kind_changed:
169
                self.assertTrue(expected_kind_changed_entry in
170
                    kind_changed_files, "%s is not kind-changed, %s are" % (
171
                    str(expected_kind_changed_entry), kind_changed_files))
0.65.4 by James Westby
Make the rename handling more robust.
172
0.80.1 by Ian Clatworthy
basic units tests for filemodify
173
    def assertContent(self, branch, tree, path, content):
174
        file_id = tree.inventory.path2id(path)
175
        branch.lock_read()
176
        self.addCleanup(branch.unlock)
177
        self.assertEqual(tree.get_file_text(file_id), content)
178
179
    def assertSymlinkTarget(self, branch, tree, path, target):
180
        file_id = tree.inventory.path2id(path)
181
        branch.lock_read()
182
        self.addCleanup(branch.unlock)
183
        self.assertEqual(tree.get_symlink_target(file_id), target)
184
0.80.4 by Ian Clatworthy
file executable off <-> on tests
185
    def assertExecutable(self, branch, tree, path, executable):
186
        file_id = tree.inventory.path2id(path)
187
        branch.lock_read()
188
        self.addCleanup(branch.unlock)
189
        self.assertEqual(tree.is_executable(file_id), executable)
190
0.80.1 by Ian Clatworthy
basic units tests for filemodify
191
    def assertRevisionRoot(self, revtree, path):
192
        self.assertEqual(revtree.get_revision_id(),
193
                         revtree.inventory.root.children[path].revision)
194
195
0.132.1 by Samuel Bronson
Add test for bug #401249.
196
class TestImportToPackTag(TestCaseForGenericProcessor):
197
198
    def file_command_iter(self, path, kind='file', content='aaa',
199
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
200
        # Revno 1: create a file or symlink
201
        # Revno 2: modify it
202
        if to_kind is None:
203
            to_kind = kind
204
        if to_executable is None:
205
            to_executable = executable
206
        def command_list():
207
            author = ['', 'bugs@a.com', time.time(), time.timezone]
208
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
209
            def files_one():
0.64.317 by Jelmer Vernooij
Merge test for bug 410249.
210
                yield commands.FileModifyCommand(path,
211
                    kind_to_mode(kind, executable), None, content)
0.132.1 by Samuel Bronson
Add test for bug #401249.
212
            yield commands.CommitCommand('head', '1', author,
213
                committer, "commit 1", None, [], files_one)
214
            def files_two():
0.64.317 by Jelmer Vernooij
Merge test for bug 410249.
215
                yield commands.FileModifyCommand(path,
216
                    kind_to_mode(to_kind, to_executable), None, to_content)
0.132.3 by Samuel Bronson
It looks like #401249 also applies to "branch ... from <refname>".
217
218
            # pass "head" for from_ to show that #401249 is worse than I knew
0.132.1 by Samuel Bronson
Add test for bug #401249.
219
            yield commands.CommitCommand('head', '2', author,
0.132.3 by Samuel Bronson
It looks like #401249 also applies to "branch ... from <refname>".
220
                committer, "commit 2", "head", [], files_two)
221
0.132.1 by Samuel Bronson
Add test for bug #401249.
222
            yield commands.TagCommand('tag1', ':1', committer, "tag 1")
0.132.3 by Samuel Bronson
It looks like #401249 also applies to "branch ... from <refname>".
223
224
            # pass "head" for from_ to demonstrate #401249
0.132.1 by Samuel Bronson
Add test for bug #401249.
225
            yield commands.TagCommand('tag2', 'head', committer, "tag 2")
226
        return command_list
227
228
    def test_tag(self):
229
        handler, branch = self.get_handler()
230
        path = 'a'
0.64.317 by Jelmer Vernooij
Merge test for bug 410249.
231
        raise tests.KnownFailure("non-mark committish not yet supported"
232
                                 "- bug #410249")
0.132.1 by Samuel Bronson
Add test for bug #401249.
233
        handler.process(self.file_command_iter(path))
234
0.64.317 by Jelmer Vernooij
Merge test for bug 410249.
235
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
236
class TestImportToPackModify(TestCaseForGenericProcessor):
0.80.1 by Ian Clatworthy
basic units tests for filemodify
237
0.80.3 by Ian Clatworthy
file <-> symlink change tests
238
    def file_command_iter(self, path, kind='file', content='aaa',
0.80.4 by Ian Clatworthy
file executable off <-> on tests
239
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
240
0.80.4 by Ian Clatworthy
file executable off <-> on tests
241
        # Revno 1: create a file or symlink
242
        # Revno 2: modify it
0.80.3 by Ian Clatworthy
file <-> symlink change tests
243
        if to_kind is None:
244
            to_kind = kind
0.80.4 by Ian Clatworthy
file executable off <-> on tests
245
        if to_executable is None:
246
            to_executable = executable
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
247
        mode = kind_to_mode(kind, executable)
248
        to_mode = kind_to_mode(to_kind, to_executable)
0.80.1 by Ian Clatworthy
basic units tests for filemodify
249
        def command_list():
250
            author = ['', 'bugs@a.com', time.time(), time.timezone]
251
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
252
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
253
                yield commands.FileModifyCommand(path, mode, None, content)
0.80.1 by Ian Clatworthy
basic units tests for filemodify
254
            yield commands.CommitCommand('head', '1', author,
255
                committer, "commit 1", None, [], files_one)
256
            def files_two():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
257
                yield commands.FileModifyCommand(path, to_mode, None, to_content)
0.80.1 by Ian Clatworthy
basic units tests for filemodify
258
            yield commands.CommitCommand('head', '2', author,
259
                committer, "commit 2", ":1", [], files_two)
260
        return command_list
261
262
    def test_modify_file_in_root(self):
263
        handler, branch = self.get_handler()
264
        path = 'a'
265
        handler.process(self.file_command_iter(path))
266
        revtree0, revtree1 = self.assertChanges(branch, 1,
267
            expected_added=[(path,)])
268
        revtree1, revtree2 = self.assertChanges(branch, 2,
269
            expected_modified=[(path,)])
270
        self.assertContent(branch, revtree1, path, "aaa")
271
        self.assertContent(branch, revtree2, path, "bbb")
272
        self.assertRevisionRoot(revtree1, path)
273
        self.assertRevisionRoot(revtree2, path)
274
275
    def test_modify_file_in_subdir(self):
276
        handler, branch = self.get_handler()
277
        path = 'a/a'
278
        handler.process(self.file_command_iter(path))
279
        revtree0, revtree1 = self.assertChanges(branch, 1,
280
            expected_added=[('a',), (path,)])
281
        revtree1, revtree2 = self.assertChanges(branch, 2,
282
            expected_modified=[(path,)])
283
        self.assertContent(branch, revtree1, path, "aaa")
284
        self.assertContent(branch, revtree2, path, "bbb")
285
286
    def test_modify_symlink_in_root(self):
287
        handler, branch = self.get_handler()
288
        path = 'a'
289
        handler.process(self.file_command_iter(path, kind='symlink'))
290
        revtree1, revtree2 = self.assertChanges(branch, 2,
291
            expected_modified=[(path,)])
292
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
293
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
294
        self.assertRevisionRoot(revtree1, path)
295
        self.assertRevisionRoot(revtree2, path)
296
297
    def test_modify_symlink_in_subdir(self):
298
        handler, branch = self.get_handler()
299
        path = 'a/a'
300
        handler.process(self.file_command_iter(path, kind='symlink'))
301
        revtree0, revtree1 = self.assertChanges(branch, 1,
302
            expected_added=[('a',), (path,)])
303
        revtree1, revtree2 = self.assertChanges(branch, 2,
304
            expected_modified=[(path,)])
305
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
306
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
307
0.80.3 by Ian Clatworthy
file <-> symlink change tests
308
    def test_modify_file_becomes_symlink(self):
309
        handler, branch = self.get_handler()
310
        path = 'a/a'
311
        handler.process(self.file_command_iter(path,
312
            kind='file', to_kind='symlink'))
313
        revtree0, revtree1 = self.assertChanges(branch, 1,
314
            expected_added=[('a',), (path,)])
315
        revtree1, revtree2 = self.assertChanges(branch, 2,
316
            expected_kind_changed=[(path, 'file', 'symlink')])
317
        self.assertContent(branch, revtree1, path, "aaa")
318
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
319
320
    def test_modify_symlink_becomes_file(self):
321
        handler, branch = self.get_handler()
322
        path = 'a/a'
323
        handler.process(self.file_command_iter(path,
324
            kind='symlink', to_kind='file'))
325
        revtree0, revtree1 = self.assertChanges(branch, 1,
326
            expected_added=[('a',), (path,)])
327
        revtree1, revtree2 = self.assertChanges(branch, 2,
328
            expected_kind_changed=[(path, 'symlink', 'file')])
329
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
330
        self.assertContent(branch, revtree2, path, "bbb")
331
0.80.4 by Ian Clatworthy
file executable off <-> on tests
332
    def test_modify_file_now_executable(self):
333
        handler, branch = self.get_handler()
334
        path = 'a/a'
335
        handler.process(self.file_command_iter(path,
336
            executable=False, to_executable=True, to_content='aaa'))
337
        revtree0, revtree1 = self.assertChanges(branch, 1,
338
            expected_added=[('a',), (path,)])
339
        revtree1, revtree2 = self.assertChanges(branch, 2,
340
            expected_modified=[(path,)])
341
        self.assertExecutable(branch, revtree1, path, False)
342
        self.assertExecutable(branch, revtree2, path, True)
343
344
    def test_modify_file_no_longer_executable(self):
345
        handler, branch = self.get_handler()
346
        path = 'a/a'
347
        handler.process(self.file_command_iter(path,
348
            executable=True, to_executable=False, to_content='aaa'))
349
        revtree0, revtree1 = self.assertChanges(branch, 1,
350
            expected_added=[('a',), (path,)])
351
        revtree1, revtree2 = self.assertChanges(branch, 2,
352
            expected_modified=[(path,)])
353
        self.assertExecutable(branch, revtree1, path, True)
354
        self.assertExecutable(branch, revtree2, path, False)
355
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
356
0.99.5 by Ian Clatworthy
handle adding the same file twice in the one commit
357
class TestImportToPackModifyTwice(TestCaseForGenericProcessor):
358
    """This tests when the same file is modified twice in the one commit.
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
359
0.99.5 by Ian Clatworthy
handle adding the same file twice in the one commit
360
    Note: hg-fast-export produces data like this on occasions.
361
    """
362
363
    def file_command_iter(self, path, kind='file', content='aaa',
364
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
365
0.99.5 by Ian Clatworthy
handle adding the same file twice in the one commit
366
        # Revno 1: create a file twice
367
        if to_kind is None:
368
            to_kind = kind
369
        if to_executable is None:
370
            to_executable = executable
371
        def command_list():
372
            author = ['', 'bugs@a.com', time.time(), time.timezone]
373
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
374
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
375
                yield commands.FileModifyCommand(path, kind_to_mode(kind, executable),
0.99.5 by Ian Clatworthy
handle adding the same file twice in the one commit
376
                        None, content)
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
377
                yield commands.FileModifyCommand(path, kind_to_mode(to_kind, to_executable),
0.99.5 by Ian Clatworthy
handle adding the same file twice in the one commit
378
                        None, to_content)
379
            yield commands.CommitCommand('head', '1', author,
380
                committer, "commit 1", None, [], files_one)
381
        return command_list
382
383
    def test_modify_file_twice_in_root(self):
384
        handler, branch = self.get_handler()
385
        path = 'a'
386
        handler.process(self.file_command_iter(path))
387
        revtree0, revtree1 = self.assertChanges(branch, 1,
388
            expected_added=[(path,)])
389
        self.assertContent(branch, revtree1, path, "aaa")
390
        self.assertRevisionRoot(revtree1, path)
391
392
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
393
class TestImportToPackModifyTricky(TestCaseForGenericProcessor):
0.80.5 by Ian Clatworthy
file/symlink <-> directory change tests & fix
394
395
    def file_command_iter(self, path1, path2, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
396
0.80.5 by Ian Clatworthy
file/symlink <-> directory change tests & fix
397
        # Revno 1: create a file or symlink in a directory
398
        # Revno 2: create a second file that implicitly deletes the
399
        # first one because either:
400
        # * the new file is a in directory with the old file name
401
        # * the new file has the same name as the directory of the first
402
        def command_list():
403
            author = ['', 'bugs@a.com', time.time(), time.timezone]
404
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
405
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
406
                yield commands.FileModifyCommand(path1, kind_to_mode(kind, False),
0.80.5 by Ian Clatworthy
file/symlink <-> directory change tests & fix
407
                        None, "aaa")
408
            yield commands.CommitCommand('head', '1', author,
409
                committer, "commit 1", None, [], files_one)
410
            def files_two():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
411
                yield commands.FileModifyCommand(path2, kind_to_mode(kind, False),
0.80.5 by Ian Clatworthy
file/symlink <-> directory change tests & fix
412
                        None, "bbb")
413
            yield commands.CommitCommand('head', '2', author,
414
                committer, "commit 2", ":1", [], files_two)
415
        return command_list
416
417
418
    def test_modify_file_becomes_directory(self):
419
        handler, branch = self.get_handler()
420
        path1 = 'a/b'
421
        path2 = 'a/b/c'
422
        handler.process(self.file_command_iter(path1, path2))
423
        revtree0, revtree1 = self.assertChanges(branch, 1,
424
            expected_added=[('a',), (path1,)])
425
        revtree1, revtree2 = self.assertChanges(branch, 2,
426
            expected_added=[(path2,)],
427
            expected_kind_changed=[(path1, 'file', 'directory')])
428
        self.assertContent(branch, revtree1, path1, "aaa")
429
        self.assertContent(branch, revtree2, path2, "bbb")
430
431
    def test_modify_directory_becomes_file(self):
432
        handler, branch = self.get_handler()
433
        path1 = 'a/b/c'
434
        path2 = 'a/b'
435
        handler.process(self.file_command_iter(path1, path2))
436
        revtree0, revtree1 = self.assertChanges(branch, 1,
437
            expected_added=[('a',), ('a/b',), (path1,)])
438
        revtree1, revtree2 = self.assertChanges(branch, 2,
439
            expected_removed=[(path1,),],
440
            expected_kind_changed=[(path2, 'directory', 'file')])
441
        self.assertContent(branch, revtree1, path1, "aaa")
442
        self.assertContent(branch, revtree2, path2, "bbb")
443
444
    def test_modify_symlink_becomes_directory(self):
445
        handler, branch = self.get_handler()
446
        path1 = 'a/b'
447
        path2 = 'a/b/c'
448
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
449
        revtree0, revtree1 = self.assertChanges(branch, 1,
450
            expected_added=[('a',), (path1,)])
451
        revtree1, revtree2 = self.assertChanges(branch, 2,
452
            expected_added=[(path2,)],
453
            expected_kind_changed=[(path1, 'symlink', 'directory')])
454
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
455
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
456
457
    def test_modify_directory_becomes_symlink(self):
458
        handler, branch = self.get_handler()
459
        path1 = 'a/b/c'
460
        path2 = 'a/b'
461
        handler.process(self.file_command_iter(path1, path2, 'symlink'))
462
        revtree0, revtree1 = self.assertChanges(branch, 1,
463
            expected_added=[('a',), ('a/b',), (path1,)])
464
        revtree1, revtree2 = self.assertChanges(branch, 2,
465
            expected_removed=[(path1,),],
466
            expected_kind_changed=[(path2, 'directory', 'symlink')])
467
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
468
        self.assertSymlinkTarget(branch, revtree2, path2, "bbb")
469
470
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
471
class TestImportToPackDelete(TestCaseForGenericProcessor):
0.80.2 by Ian Clatworthy
basic delete tests
472
473
    def file_command_iter(self, path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
474
0.80.4 by Ian Clatworthy
file executable off <-> on tests
475
        # Revno 1: create a file or symlink
476
        # Revno 2: delete it
0.80.2 by Ian Clatworthy
basic delete tests
477
        def command_list():
478
            author = ['', 'bugs@a.com', time.time(), time.timezone]
479
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
480
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
481
                yield commands.FileModifyCommand(path, kind_to_mode(kind, False),
0.80.2 by Ian Clatworthy
basic delete tests
482
                        None, "aaa")
483
            yield commands.CommitCommand('head', '1', author,
484
                committer, "commit 1", None, [], files_one)
485
            def files_two():
486
                yield commands.FileDeleteCommand(path)
487
            yield commands.CommitCommand('head', '2', author,
488
                committer, "commit 2", ":1", [], files_two)
489
        return command_list
490
491
    def test_delete_file_in_root(self):
492
        handler, branch = self.get_handler()
493
        path = 'a'
494
        handler.process(self.file_command_iter(path))
495
        revtree0, revtree1 = self.assertChanges(branch, 1,
496
            expected_added=[(path,)])
497
        revtree1, revtree2 = self.assertChanges(branch, 2,
498
            expected_removed=[(path,)])
499
        self.assertContent(branch, revtree1, path, "aaa")
500
        self.assertRevisionRoot(revtree1, path)
501
502
    def test_delete_file_in_subdir(self):
503
        handler, branch = self.get_handler()
504
        path = 'a/a'
505
        handler.process(self.file_command_iter(path))
506
        revtree0, revtree1 = self.assertChanges(branch, 1,
507
            expected_added=[('a',), (path,)])
508
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.96.1 by Ian Clatworthy
update existing tests to reflect implicit directory pruning bahaviour
509
            expected_removed=[('a',), (path,)])
0.80.2 by Ian Clatworthy
basic delete tests
510
        self.assertContent(branch, revtree1, path, "aaa")
511
512
    def test_delete_symlink_in_root(self):
513
        handler, branch = self.get_handler()
514
        path = 'a'
515
        handler.process(self.file_command_iter(path, kind='symlink'))
516
        revtree1, revtree2 = self.assertChanges(branch, 2,
517
            expected_removed=[(path,)])
518
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
519
        self.assertRevisionRoot(revtree1, path)
520
521
    def test_delete_symlink_in_subdir(self):
522
        handler, branch = self.get_handler()
523
        path = 'a/a'
524
        handler.process(self.file_command_iter(path, kind='symlink'))
525
        revtree0, revtree1 = self.assertChanges(branch, 1,
526
            expected_added=[('a',), (path,)])
527
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.96.1 by Ian Clatworthy
update existing tests to reflect implicit directory pruning bahaviour
528
            expected_removed=[('a',), (path,)])
0.80.2 by Ian Clatworthy
basic delete tests
529
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
530
0.96.2 by Ian Clatworthy
test and fix for implicit directory delete recursing up
531
    def test_delete_file_in_deep_subdir(self):
532
        handler, branch = self.get_handler()
533
        path = 'a/b/c/d'
534
        handler.process(self.file_command_iter(path))
535
        revtree0, revtree1 = self.assertChanges(branch, 1,
536
            expected_added=[('a',), ('a/b',), ('a/b/c',), (path,)])
537
        revtree1, revtree2 = self.assertChanges(branch, 2,
538
            expected_removed=[('a',), ('a/b',), ('a/b/c',), (path,)])
539
        self.assertContent(branch, revtree1, path, "aaa")
540
0.80.2 by Ian Clatworthy
basic delete tests
541
0.99.7 by Ian Clatworthy
handle a delete of a newly added file
542
class TestImportToPackDeleteNew(TestCaseForGenericProcessor):
543
    """Test deletion of a newly added file."""
544
545
    def file_command_iter(self, path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
546
0.99.7 by Ian Clatworthy
handle a delete of a newly added file
547
        # Revno 1: create a file or symlink then delete it
548
        def command_list():
549
            author = ['', 'bugs@a.com', time.time(), time.timezone]
550
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
551
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
552
                yield commands.FileModifyCommand(path, kind_to_mode(kind, False),
0.99.7 by Ian Clatworthy
handle a delete of a newly added file
553
                        None, "aaa")
554
                yield commands.FileDeleteCommand(path)
555
            yield commands.CommitCommand('head', '1', author,
556
                committer, "commit 1", None, [], files_one)
557
        return command_list
558
559
    def test_delete_new_file_in_root(self):
560
        handler, branch = self.get_handler()
561
        path = 'a'
562
        handler.process(self.file_command_iter(path))
563
        revtree0, revtree1 = self.assertChanges(branch, 1,)
564
565
    def test_delete_new_file_in_subdir(self):
566
        handler, branch = self.get_handler()
567
        path = 'a/a'
568
        handler.process(self.file_command_iter(path))
569
        revtree0, revtree1 = self.assertChanges(branch, 1,)
570
571
    def test_delete_new_symlink_in_root(self):
572
        handler, branch = self.get_handler()
573
        path = 'a'
574
        handler.process(self.file_command_iter(path, kind='symlink'))
575
        revtree0, revtree1 = self.assertChanges(branch, 1,)
576
577
    def test_delete_new_symlink_in_subdir(self):
578
        handler, branch = self.get_handler()
579
        path = 'a/a'
580
        handler.process(self.file_command_iter(path, kind='symlink'))
581
        revtree0, revtree1 = self.assertChanges(branch, 1,)
582
583
    def test_delete_new_file_in_deep_subdir(self):
584
        handler, branch = self.get_handler()
585
        path = 'a/b/c/d'
586
        handler.process(self.file_command_iter(path))
587
        revtree0, revtree1 = self.assertChanges(branch, 1,)
588
589
0.101.1 by Tom Widmer
Add test cases to check deletions from multiple levels in a tree still cause pruning of empty dirs to happen correctly.
590
class TestImportToPackDeleteMultiLevel(TestCaseForGenericProcessor):
591
592
    def file_command_iter(self, paths, paths_to_delete):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
593
0.101.1 by Tom Widmer
Add test cases to check deletions from multiple levels in a tree still cause pruning of empty dirs to happen correctly.
594
        # Revno 1: create multiple files
595
        # Revno 2: delete multiple files
596
        def command_list():
597
            author = ['', 'bugs@a.com', time.time(), time.timezone]
598
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
599
            def files_one():
600
                for i, path in enumerate(paths):
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
601
                    yield commands.FileModifyCommand(path, kind_to_mode('file', False),
0.101.1 by Tom Widmer
Add test cases to check deletions from multiple levels in a tree still cause pruning of empty dirs to happen correctly.
602
                            None, "aaa%d" % i)
603
            yield commands.CommitCommand('head', '1', author,
604
                committer, "commit 1", None, [], files_one)
605
            def files_two():
606
                for path in paths_to_delete:
607
                    yield commands.FileDeleteCommand(path)
608
            yield commands.CommitCommand('head', '2', author,
609
                committer, "commit 2", ":1", [], files_two)
610
        return command_list
611
612
    def test_delete_files_in_multiple_levels(self):
613
        handler, branch = self.get_handler()
614
        paths = ['a/b/c', 'a/b/d/e']
615
        paths_to_delete = ['a/b/c', 'a/b/d/e']
616
        handler.process(self.file_command_iter(paths, paths_to_delete))
617
        revtree0, revtree1 = self.assertChanges(branch, 1,
618
            expected_added=[
619
                ('a',), ('a/b',), ('a/b/c',),
620
                ('a/b/d',), ('a/b/d/e',),
621
                ])
622
        revtree1, revtree2 = self.assertChanges(branch, 2,
623
            expected_removed=[
624
                ('a',), ('a/b',), ('a/b/c',),
625
                ('a/b/d',), ('a/b/d/e',),
626
                ])
627
628
    def test_delete_file_single_level(self):
629
        handler, branch = self.get_handler()
630
        paths = ['a/b/c', 'a/b/d/e']
631
        paths_to_delete = ['a/b/d/e']
632
        handler.process(self.file_command_iter(paths, paths_to_delete))
633
        revtree0, revtree1 = self.assertChanges(branch, 1,
634
            expected_added=[
635
                ('a',), ('a/b',), ('a/b/c',),
636
                ('a/b/d',), ('a/b/d/e',),
637
                ])
638
        revtree1, revtree2 = self.assertChanges(branch, 2,
639
            expected_removed=[
640
                ('a/b/d',), ('a/b/d/e',),
641
                ])
642
643
    def test_delete_file_complex_level(self):
644
        handler, branch = self.get_handler()
645
        paths = ['a/b/c', 'a/b/d/e', 'a/f/g', 'a/h', 'a/b/d/i/j']
646
        paths_to_delete = ['a/b/c', 'a/b/d/e', 'a/f/g', 'a/b/d/i/j']
647
        handler.process(self.file_command_iter(paths, paths_to_delete))
648
        revtree0, revtree1 = self.assertChanges(branch, 1,
649
            expected_added=[
650
                ('a',), ('a/b',), ('a/b/c',),
651
                ('a/b/d',), ('a/b/d/e',),
652
                ('a/f',), ('a/f/g',),
653
                ('a/h',),
654
                ('a/b/d/i',), ('a/b/d/i/j',),
655
                ])
656
        revtree1, revtree2 = self.assertChanges(branch, 2,
657
            expected_removed=[
658
                ('a/b',), ('a/b/c',),
659
                ('a/b/d',), ('a/b/d/e',),
660
                ('a/f',), ('a/f/g',),
661
                ('a/b/d/i',), ('a/b/d/i/j',),
662
                ])
663
0.99.13 by Ian Clatworthy
Handle delete then add of a file/symlink in the one commit
664
class TestImportToPackDeleteThenAdd(TestCaseForGenericProcessor):
665
    """Test delete followed by an add. Merges can cause this."""
666
667
    def file_command_iter(self, path, kind='file', content='aaa',
668
        executable=False, to_kind=None, to_content='bbb', to_executable=None):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
669
0.99.13 by Ian Clatworthy
Handle delete then add of a file/symlink in the one commit
670
        # Revno 1: create a file or symlink
671
        # Revno 2: delete it and add it
672
        if to_kind is None:
673
            to_kind = kind
674
        if to_executable is None:
675
            to_executable = executable
676
        def command_list():
677
            author = ['', 'bugs@a.com', time.time(), time.timezone]
678
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
679
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
680
                yield commands.FileModifyCommand(path, kind_to_mode(kind, executable),
0.99.13 by Ian Clatworthy
Handle delete then add of a file/symlink in the one commit
681
                        None, content)
682
            yield commands.CommitCommand('head', '1', author,
683
                committer, "commit 1", None, [], files_one)
684
            def files_two():
685
                yield commands.FileDeleteCommand(path)
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
686
                yield commands.FileModifyCommand(path, kind_to_mode(to_kind, to_executable),
0.99.13 by Ian Clatworthy
Handle delete then add of a file/symlink in the one commit
687
                        None, to_content)
688
            yield commands.CommitCommand('head', '2', author,
689
                committer, "commit 2", ":1", [], files_two)
690
        return command_list
691
692
    def test_delete_then_add_file_in_root(self):
693
        handler, branch = self.get_handler()
694
        path = 'a'
695
        handler.process(self.file_command_iter(path))
696
        revtree0, revtree1 = self.assertChanges(branch, 1,
697
            expected_added=[(path,)])
698
        revtree1, revtree2 = self.assertChanges(branch, 2,
699
            expected_removed=[(path,)],
700
            expected_added=[(path,)])
701
        self.assertContent(branch, revtree1, path, "aaa")
702
        self.assertContent(branch, revtree2, path, "bbb")
703
        self.assertRevisionRoot(revtree1, path)
704
        self.assertRevisionRoot(revtree2, path)
705
706
    def test_delete_then_add_file_in_subdir(self):
707
        handler, branch = self.get_handler()
708
        path = 'a/a'
709
        handler.process(self.file_command_iter(path))
710
        revtree0, revtree1 = self.assertChanges(branch, 1,
711
            expected_added=[('a',), (path,)])
712
        revtree1, revtree2 = self.assertChanges(branch, 2,
713
            expected_removed=[(path,)],
714
            expected_added=[(path,)])
715
        self.assertContent(branch, revtree1, path, "aaa")
716
        self.assertContent(branch, revtree2, path, "bbb")
717
718
    def test_delete_then_add_symlink_in_root(self):
719
        handler, branch = self.get_handler()
720
        path = 'a'
721
        handler.process(self.file_command_iter(path, kind='symlink'))
722
        revtree1, revtree2 = self.assertChanges(branch, 2,
723
            expected_removed=[(path,)],
724
            expected_added=[(path,)])
725
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
726
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
727
        self.assertRevisionRoot(revtree1, path)
728
        self.assertRevisionRoot(revtree2, path)
729
730
    def test_delete_then_add_symlink_in_subdir(self):
731
        handler, branch = self.get_handler()
732
        path = 'a/a'
733
        handler.process(self.file_command_iter(path, kind='symlink'))
734
        revtree0, revtree1 = self.assertChanges(branch, 1,
735
            expected_added=[('a',), (path,)])
736
        revtree1, revtree2 = self.assertChanges(branch, 2,
737
            expected_removed=[(path,)],
738
            expected_added=[(path,)])
739
        self.assertSymlinkTarget(branch, revtree1, path, "aaa")
740
        self.assertSymlinkTarget(branch, revtree2, path, "bbb")
741
742
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
743
class TestImportToPackDeleteDirectory(TestCaseForGenericProcessor):
0.80.7 by Ian Clatworthy
add directory delete test
744
745
    def file_command_iter(self, paths, dir):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
746
0.80.7 by Ian Clatworthy
add directory delete test
747
        # Revno 1: create multiple files
748
        # Revno 2: delete a directory holding those files
749
        def command_list():
750
            author = ['', 'bugs@a.com', time.time(), time.timezone]
751
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
752
            def files_one():
753
                for i, path in enumerate(paths):
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
754
                    yield commands.FileModifyCommand(path, kind_to_mode('file', False),
0.80.7 by Ian Clatworthy
add directory delete test
755
                            None, "aaa%d" % i)
756
            yield commands.CommitCommand('head', '1', author,
757
                committer, "commit 1", None, [], files_one)
758
            def files_two():
759
                yield commands.FileDeleteCommand(dir)
760
            yield commands.CommitCommand('head', '2', author,
761
                committer, "commit 2", ":1", [], files_two)
762
        return command_list
763
764
    def test_delete_dir(self):
765
        handler, branch = self.get_handler()
766
        paths = ['a/b/c', 'a/b/d', 'a/b/e/f', 'a/g']
767
        dir = 'a/b'
768
        handler.process(self.file_command_iter(paths, dir))
769
        revtree0, revtree1 = self.assertChanges(branch, 1,
770
            expected_added=[
771
                ('a',), ('a/b',), ('a/b/c',),
772
                ('a/b/d',),
773
                ('a/b/e',), ('a/b/e/f',),
774
                ('a/g',),
775
                ])
776
        revtree1, revtree2 = self.assertChanges(branch, 2,
777
            expected_removed=[
778
                ('a/b',), ('a/b/c',),
779
                ('a/b/d',),
780
                ('a/b/e',), ('a/b/e/f',),
781
                ])
782
783
0.99.21 by Ian Clatworthy
Handle deleting a directory then adding a file within it in the same commit
784
class TestImportToPackDeleteDirectoryThenAddFile(TestCaseForGenericProcessor):
785
    """Test deleting a directory then adding a file in the same commit."""
786
787
    def file_command_iter(self, paths, dir, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
788
0.99.21 by Ian Clatworthy
Handle deleting a directory then adding a file within it in the same commit
789
        # Revno 1: create files in a directory
790
        # Revno 2: delete the directory then add a file into it
791
        def command_list():
792
            author = ['', 'bugs@a.com', time.time(), time.timezone]
793
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
794
            def files_one():
795
                for i, path in enumerate(paths):
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
796
                    yield commands.FileModifyCommand(path, kind_to_mode(kind, False),
0.99.21 by Ian Clatworthy
Handle deleting a directory then adding a file within it in the same commit
797
                            None, "aaa%d" % i)
798
            yield commands.CommitCommand('head', '1', author,
799
                committer, "commit 1", None, [], files_one)
800
            def files_two():
801
                yield commands.FileDeleteCommand(dir)
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
802
                yield commands.FileModifyCommand(new_path, kind_to_mode(kind, False),
0.99.21 by Ian Clatworthy
Handle deleting a directory then adding a file within it in the same commit
803
                        None, "bbb")
804
            yield commands.CommitCommand('head', '2', author,
805
                committer, "commit 2", ":1", [], files_two)
806
        return command_list
807
808
    def test_delete_dir_then_add_file(self):
809
        handler, branch = self.get_handler()
810
        paths = ['a/b/c', 'a/b/d']
811
        dir = 'a/b'
812
        new_path = 'a/b/z'
813
        handler.process(self.file_command_iter(paths, dir, new_path))
814
        revtree0, revtree1 = self.assertChanges(branch, 1,
815
            expected_added=[('a',), ('a/b',), ('a/b/c',), ('a/b/d',),])
816
        revtree1, revtree2 = self.assertChanges(branch, 2,
817
            expected_removed=[('a/b',), ('a/b/c',), ('a/b/d',)],
818
            expected_added=[('a/b',), ('a/b/z',)])
819
        self.assertContent(branch, revtree2, new_path, "bbb")
820
821
    def test_delete_dir_then_add_symlink(self):
822
        handler, branch = self.get_handler()
823
        paths = ['a/b/c', 'a/b/d']
824
        dir = 'a/b'
825
        new_path = 'a/b/z'
826
        handler.process(self.file_command_iter(paths, dir, new_path, 'symlink'))
827
        revtree0, revtree1 = self.assertChanges(branch, 1,
828
            expected_added=[('a',), ('a/b',), ('a/b/c',), ('a/b/d',),])
829
        revtree1, revtree2 = self.assertChanges(branch, 2,
830
            expected_removed=[('a/b',), ('a/b/c',), ('a/b/d',)],
831
            expected_added=[('a/b',), ('a/b/z',)])
832
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
833
834
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
835
class TestImportToPackRename(TestCaseForGenericProcessor):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
836
0.99.16 by Ian Clatworthy
add tests for symlink renaming
837
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
838
0.80.4 by Ian Clatworthy
file executable off <-> on tests
839
        # Revno 1: create a file or symlink
840
        # Revno 2: rename it
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
841
        def command_list():
842
            author = ['', 'bugs@a.com', time.time(), time.timezone]
843
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
844
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
845
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
846
                        None, "aaa")
847
            yield commands.CommitCommand('head', '1', author,
848
                committer, "commit 1", None, [], files_one)
849
            def files_two():
850
                yield commands.FileRenameCommand(old_path, new_path)
851
            yield commands.CommitCommand('head', '2', author,
852
                committer, "commit 2", ":1", [], files_two)
853
        return command_list
854
0.99.16 by Ian Clatworthy
add tests for symlink renaming
855
    def test_rename_file_in_root(self):
856
        handler, branch = self.get_handler()
857
        old_path = 'a'
858
        new_path = 'b'
859
        handler.process(self.get_command_iter(old_path, new_path))
860
        revtree1, revtree2 = self.assertChanges(branch, 2,
861
            expected_renamed=[(old_path, new_path)])
862
        self.assertRevisionRoot(revtree1, old_path)
863
        self.assertRevisionRoot(revtree2, new_path)
864
865
    def test_rename_symlink_in_root(self):
866
        handler, branch = self.get_handler()
867
        old_path = 'a'
868
        new_path = 'b'
869
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
870
        revtree1, revtree2 = self.assertChanges(branch, 2,
871
            expected_renamed=[(old_path, new_path)])
872
        self.assertRevisionRoot(revtree1, old_path)
873
        self.assertRevisionRoot(revtree2, new_path)
874
875
    def test_rename_file_in_subdir(self):
876
        handler, branch = self.get_handler()
877
        old_path = 'a/a'
878
        new_path = 'a/b'
879
        handler.process(self.get_command_iter(old_path, new_path))
880
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)])
881
882
    def test_rename_symlink_in_subdir(self):
883
        handler, branch = self.get_handler()
884
        old_path = 'a/a'
885
        new_path = 'a/b'
886
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
887
        self.assertChanges(branch, 2, expected_renamed=[(old_path, new_path)])
888
889
    def test_rename_file_to_new_dir(self):
890
        handler, branch = self.get_handler()
891
        old_path = 'a/a'
892
        new_path = 'b/a'
893
        handler.process(self.get_command_iter(old_path, new_path))
894
        self.assertChanges(branch, 2,
895
            expected_renamed=[(old_path, new_path)],
896
            expected_added=[('b',)],
897
            expected_removed=[('a',)])
898
899
    def test_rename_symlink_to_new_dir(self):
900
        handler, branch = self.get_handler()
901
        old_path = 'a/a'
902
        new_path = 'b/a'
903
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
0.96.1 by Ian Clatworthy
update existing tests to reflect implicit directory pruning bahaviour
904
        self.assertChanges(branch, 2,
905
            expected_renamed=[(old_path, new_path)],
906
            expected_added=[('b',)],
907
            expected_removed=[('a',)])
0.64.74 by Ian Clatworthy
fix symlink importing
908
909
0.99.6 by Ian Clatworthy
Handle rename of a just added file
910
class TestImportToPackRenameNew(TestCaseForGenericProcessor):
0.99.8 by Ian Clatworthy
handle copy of a newly added file
911
    """Test rename of a newly added file."""
0.99.6 by Ian Clatworthy
Handle rename of a just added file
912
0.99.16 by Ian Clatworthy
add tests for symlink renaming
913
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
914
0.99.6 by Ian Clatworthy
Handle rename of a just added file
915
        # Revno 1: create a file and rename it
916
        def command_list():
917
            author = ['', 'bugs@a.com', time.time(), time.timezone]
918
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
919
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
920
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.99.6 by Ian Clatworthy
Handle rename of a just added file
921
                        None, "aaa")
922
                yield commands.FileRenameCommand(old_path, new_path)
923
            yield commands.CommitCommand('head', '1', author,
924
                committer, "commit 1", None, [], files_one)
925
        return command_list
926
0.99.16 by Ian Clatworthy
add tests for symlink renaming
927
    def test_rename_new_file_in_root(self):
928
        handler, branch = self.get_handler()
929
        old_path = 'a'
930
        new_path = 'b'
931
        handler.process(self.get_command_iter(old_path, new_path))
932
        revtree0, revtree1 = self.assertChanges(branch, 1,
933
            expected_added=[(new_path,)])
934
        self.assertRevisionRoot(revtree1, new_path)
935
936
    def test_rename_new_symlink_in_root(self):
937
        handler, branch = self.get_handler()
938
        old_path = 'a'
939
        new_path = 'b'
940
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
941
        revtree0, revtree1 = self.assertChanges(branch, 1,
942
            expected_added=[(new_path,)])
943
        self.assertRevisionRoot(revtree1, new_path)
944
945
    def test_rename_new_file_in_subdir(self):
946
        handler, branch = self.get_handler()
947
        old_path = 'a/a'
948
        new_path = 'a/b'
949
        handler.process(self.get_command_iter(old_path, new_path))
950
        revtree0, revtree1 = self.assertChanges(branch, 1,
951
            expected_added=[('a',), (new_path,)])
952
953
    def test_rename_new_symlink_in_subdir(self):
954
        handler, branch = self.get_handler()
955
        old_path = 'a/a'
956
        new_path = 'a/b'
957
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
0.99.6 by Ian Clatworthy
Handle rename of a just added file
958
        revtree0, revtree1 = self.assertChanges(branch, 1,
959
            expected_added=[('a',), (new_path,)])
960
961
0.99.14 by Ian Clatworthy
Add tests for renaming to a deleted destination
962
class TestImportToPackRenameToDeleted(TestCaseForGenericProcessor):
963
    """Test rename to a destination path deleted in this commit."""
964
0.99.16 by Ian Clatworthy
add tests for symlink renaming
965
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
966
0.99.14 by Ian Clatworthy
Add tests for renaming to a deleted destination
967
        # Revno 1: create two files
968
        # Revno 2: delete one, rename the other one to that path
969
        def command_list():
970
            author = ['', 'bugs@a.com', time.time(), time.timezone]
971
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
972
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
973
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.99.14 by Ian Clatworthy
Add tests for renaming to a deleted destination
974
                        None, "aaa")
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
975
                yield commands.FileModifyCommand(new_path, kind_to_mode(kind, False),
0.99.14 by Ian Clatworthy
Add tests for renaming to a deleted destination
976
                        None, "bbb")
977
            yield commands.CommitCommand('head', '1', author,
978
                committer, "commit 1", None, [], files_one)
979
            def files_two():
980
                yield commands.FileDeleteCommand(new_path)
981
                yield commands.FileRenameCommand(old_path, new_path)
982
            yield commands.CommitCommand('head', '2', author,
983
                committer, "commit 2", ":1", [], files_two)
984
        return command_list
985
0.99.16 by Ian Clatworthy
add tests for symlink renaming
986
    def test_rename_to_deleted_file_in_root(self):
987
        handler, branch = self.get_handler()
988
        old_path = 'a'
989
        new_path = 'b'
990
        handler.process(self.get_command_iter(old_path, new_path))
991
        revtree0, revtree1 = self.assertChanges(branch, 1,
992
            expected_added=[(old_path,), (new_path,)])
993
        revtree1, revtree2 = self.assertChanges(branch, 2,
994
            expected_removed=[(new_path,)],
995
            expected_renamed=[(old_path, new_path)])
996
        self.assertContent(branch, revtree1, old_path, "aaa")
997
        self.assertContent(branch, revtree1, new_path, "bbb")
998
        self.assertContent(branch, revtree2, new_path, "aaa")
999
        self.assertRevisionRoot(revtree1, old_path)
1000
        self.assertRevisionRoot(revtree1, new_path)
1001
1002
    def test_rename_to_deleted_symlink_in_root(self):
1003
        handler, branch = self.get_handler()
1004
        old_path = 'a'
1005
        new_path = 'b'
1006
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1007
        revtree0, revtree1 = self.assertChanges(branch, 1,
1008
            expected_added=[(old_path,), (new_path,)])
1009
        revtree1, revtree2 = self.assertChanges(branch, 2,
1010
            expected_removed=[(new_path,)],
1011
            expected_renamed=[(old_path, new_path)])
1012
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1013
        self.assertSymlinkTarget(branch, revtree1, new_path, "bbb")
1014
        self.assertSymlinkTarget(branch, revtree2, new_path, "aaa")
1015
        self.assertRevisionRoot(revtree1, old_path)
1016
        self.assertRevisionRoot(revtree1, new_path)
1017
1018
    def test_rename_to_deleted_file_in_subdir(self):
1019
        handler, branch = self.get_handler()
1020
        old_path = 'd/a'
1021
        new_path = 'd/b'
1022
        handler.process(self.get_command_iter(old_path, new_path))
1023
        revtree0, revtree1 = self.assertChanges(branch, 1,
1024
            expected_added=[('d',), (old_path,), (new_path,)])
1025
        revtree1, revtree2 = self.assertChanges(branch, 2,
1026
            expected_removed=[(new_path,)],
1027
            expected_renamed=[(old_path, new_path)])
1028
        self.assertContent(branch, revtree1, old_path, "aaa")
1029
        self.assertContent(branch, revtree1, new_path, "bbb")
1030
        self.assertContent(branch, revtree2, new_path, "aaa")
1031
1032
    def test_rename_to_deleted_symlink_in_subdir(self):
1033
        handler, branch = self.get_handler()
1034
        old_path = 'd/a'
1035
        new_path = 'd/b'
1036
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1037
        revtree0, revtree1 = self.assertChanges(branch, 1,
1038
            expected_added=[('d',), (old_path,), (new_path,)])
1039
        revtree1, revtree2 = self.assertChanges(branch, 2,
1040
            expected_removed=[(new_path,)],
1041
            expected_renamed=[(old_path, new_path)])
1042
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1043
        self.assertSymlinkTarget(branch, revtree1, new_path, "bbb")
1044
        self.assertSymlinkTarget(branch, revtree2, new_path, "aaa")
1045
1046
    def test_rename_to_deleted_file_in_new_dir(self):
1047
        handler, branch = self.get_handler()
1048
        old_path = 'd1/a'
1049
        new_path = 'd2/b'
1050
        handler.process(self.get_command_iter(old_path, new_path))
1051
        revtree0, revtree1 = self.assertChanges(branch, 1,
1052
            expected_added=[('d1',), (old_path,), ('d2',), (new_path,)])
1053
        revtree1, revtree2 = self.assertChanges(branch, 2,
1054
            expected_removed=[('d1',), (new_path,)],
1055
            expected_renamed=[(old_path, new_path)])
1056
        self.assertContent(branch, revtree1, old_path, "aaa")
1057
        self.assertContent(branch, revtree1, new_path, "bbb")
1058
        self.assertContent(branch, revtree2, new_path, "aaa")
1059
1060
    def test_rename_to_deleted_symlink_in_new_dir(self):
1061
        handler, branch = self.get_handler()
1062
        old_path = 'd1/a'
1063
        new_path = 'd2/b'
1064
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1065
        revtree0, revtree1 = self.assertChanges(branch, 1,
1066
            expected_added=[('d1',), (old_path,), ('d2',), (new_path,)])
1067
        revtree1, revtree2 = self.assertChanges(branch, 2,
1068
            expected_removed=[('d1',), (new_path,)],
1069
            expected_renamed=[(old_path, new_path)])
1070
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1071
        self.assertSymlinkTarget(branch, revtree1, new_path, "bbb")
1072
        self.assertSymlinkTarget(branch, revtree2, new_path, "aaa")
0.99.14 by Ian Clatworthy
Add tests for renaming to a deleted destination
1073
1074
0.99.17 by Ian Clatworthy
Handle rename of a file/symlink modified already in this commit
1075
class TestImportToPackRenameModified(TestCaseForGenericProcessor):
1076
    """Test rename of a path previously modified in this commit."""
1077
1078
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1079
0.99.17 by Ian Clatworthy
Handle rename of a file/symlink modified already in this commit
1080
        # Revno 1: create a file or symlink
1081
        # Revno 2: modify then rename it
1082
        def command_list():
1083
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1084
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1085
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1086
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.99.17 by Ian Clatworthy
Handle rename of a file/symlink modified already in this commit
1087
                        None, "aaa")
1088
            yield commands.CommitCommand('head', '1', author,
1089
                committer, "commit 1", None, [], files_one)
1090
            def files_two():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1091
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.99.17 by Ian Clatworthy
Handle rename of a file/symlink modified already in this commit
1092
                        None, "bbb")
1093
                yield commands.FileRenameCommand(old_path, new_path)
1094
            yield commands.CommitCommand('head', '2', author,
1095
                committer, "commit 2", ":1", [], files_two)
1096
        return command_list
1097
1098
    def test_rename_of_modified_file_in_root(self):
1099
        handler, branch = self.get_handler()
1100
        old_path = 'a'
1101
        new_path = 'b'
1102
        handler.process(self.get_command_iter(old_path, new_path))
1103
        revtree0, revtree1 = self.assertChanges(branch, 1,
1104
            expected_added=[(old_path,)])
1105
        # Note: the delta doesn't show the modification?
1106
        # The actual new content is validated in the assertions following.
1107
        revtree1, revtree2 = self.assertChanges(branch, 2,
1108
            expected_renamed=[(old_path, new_path)])
1109
        self.assertContent(branch, revtree1, old_path, "aaa")
1110
        self.assertContent(branch, revtree2, new_path, "bbb")
1111
        self.assertRevisionRoot(revtree1, old_path)
1112
        self.assertRevisionRoot(revtree2, new_path)
1113
1114
    def test_rename_of_modified_symlink_in_root(self):
1115
        handler, branch = self.get_handler()
1116
        old_path = 'a'
1117
        new_path = 'b'
1118
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1119
        revtree0, revtree1 = self.assertChanges(branch, 1,
1120
            expected_added=[(old_path,)])
1121
        # Note: the delta doesn't show the modification?
1122
        # The actual new content is validated in the assertions following.
1123
        revtree1, revtree2 = self.assertChanges(branch, 2,
1124
            expected_renamed=[(old_path, new_path)])
1125
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1126
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1127
        self.assertRevisionRoot(revtree1, old_path)
1128
        self.assertRevisionRoot(revtree2, new_path)
1129
1130
    def test_rename_of_modified_file_in_subdir(self):
1131
        handler, branch = self.get_handler()
1132
        old_path = 'd/a'
1133
        new_path = 'd/b'
1134
        handler.process(self.get_command_iter(old_path, new_path))
1135
        revtree0, revtree1 = self.assertChanges(branch, 1,
1136
            expected_added=[('d',), (old_path,)])
1137
        # Note: the delta doesn't show the modification?
1138
        # The actual new content is validated in the assertions following.
1139
        revtree1, revtree2 = self.assertChanges(branch, 2,
1140
            expected_renamed=[(old_path, new_path)])
1141
        self.assertContent(branch, revtree1, old_path, "aaa")
1142
        self.assertContent(branch, revtree2, new_path, "bbb")
1143
1144
    def test_rename_of_modified_symlink_in_subdir(self):
1145
        handler, branch = self.get_handler()
1146
        old_path = 'd/a'
1147
        new_path = 'd/b'
1148
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1149
        revtree0, revtree1 = self.assertChanges(branch, 1,
1150
            expected_added=[('d',), (old_path,)])
1151
        # Note: the delta doesn't show the modification?
1152
        # The actual new content is validated in the assertions following.
1153
        revtree1, revtree2 = self.assertChanges(branch, 2,
1154
            expected_renamed=[(old_path, new_path)])
1155
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1156
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1157
1158
    def test_rename_of_modified_file_to_new_dir(self):
1159
        handler, branch = self.get_handler()
1160
        old_path = 'd1/a'
1161
        new_path = 'd2/b'
1162
        handler.process(self.get_command_iter(old_path, new_path))
1163
        revtree0, revtree1 = self.assertChanges(branch, 1,
1164
            expected_added=[('d1',), (old_path,)])
1165
        # Note: the delta doesn't show the modification?
1166
        # The actual new content is validated in the assertions following.
1167
        revtree1, revtree2 = self.assertChanges(branch, 2,
1168
            expected_renamed=[(old_path, new_path)],
1169
            expected_added=[('d2',)],
1170
            expected_removed=[('d1',)])
1171
        self.assertContent(branch, revtree1, old_path, "aaa")
1172
        self.assertContent(branch, revtree2, new_path, "bbb")
1173
1174
    def test_rename_of_modified_symlink_to_new_dir(self):
1175
        handler, branch = self.get_handler()
1176
        old_path = 'd1/a'
1177
        new_path = 'd2/b'
1178
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1179
        revtree0, revtree1 = self.assertChanges(branch, 1,
1180
            expected_added=[('d1',), (old_path,)])
1181
        # Note: the delta doesn't show the modification?
1182
        # The actual new content is validated in the assertions following.
1183
        revtree1, revtree2 = self.assertChanges(branch, 2,
1184
            expected_renamed=[(old_path, new_path)],
1185
            expected_added=[('d2',)],
1186
            expected_removed=[('d1',)])
1187
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1188
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1189
1190
0.99.19 by Ian Clatworthy
Handle rename then modification of the new path
1191
class TestImportToPackRenameThenModify(TestCaseForGenericProcessor):
1192
    """Test rename of a path then modfy the new-path in the same commit."""
1193
1194
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1195
0.99.19 by Ian Clatworthy
Handle rename then modification of the new path
1196
        # Revno 1: create a file or symlink
1197
        # Revno 2: rename it then modify the newly created path
1198
        def command_list():
1199
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1200
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1201
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1202
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.99.19 by Ian Clatworthy
Handle rename then modification of the new path
1203
                        None, "aaa")
1204
            yield commands.CommitCommand('head', '1', author,
1205
                committer, "commit 1", None, [], files_one)
1206
            def files_two():
1207
                yield commands.FileRenameCommand(old_path, new_path)
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1208
                yield commands.FileModifyCommand(new_path, kind_to_mode(kind, False),
0.99.19 by Ian Clatworthy
Handle rename then modification of the new path
1209
                        None, "bbb")
1210
            yield commands.CommitCommand('head', '2', author,
1211
                committer, "commit 2", ":1", [], files_two)
1212
        return command_list
1213
1214
    def test_rename_then_modify_file_in_root(self):
1215
        handler, branch = self.get_handler()
1216
        old_path = 'a'
1217
        new_path = 'b'
1218
        handler.process(self.get_command_iter(old_path, new_path))
1219
        revtree0, revtree1 = self.assertChanges(branch, 1,
1220
            expected_added=[(old_path,)])
1221
        # Note: the delta doesn't show the modification?
1222
        # The actual new content is validated in the assertions following.
1223
        revtree1, revtree2 = self.assertChanges(branch, 2,
1224
            expected_renamed=[(old_path, new_path)])
1225
        self.assertContent(branch, revtree1, old_path, "aaa")
1226
        self.assertContent(branch, revtree2, new_path, "bbb")
1227
        self.assertRevisionRoot(revtree1, old_path)
1228
        self.assertRevisionRoot(revtree2, new_path)
1229
1230
    def test_rename_then_modify_file_in_subdir(self):
1231
        handler, branch = self.get_handler()
1232
        old_path = 'd/a'
1233
        new_path = 'd/b'
1234
        handler.process(self.get_command_iter(old_path, new_path))
1235
        revtree0, revtree1 = self.assertChanges(branch, 1,
1236
            expected_added=[('d',), (old_path,)])
1237
        # Note: the delta doesn't show the modification?
1238
        # The actual new content is validated in the assertions following.
1239
        revtree1, revtree2 = self.assertChanges(branch, 2,
1240
            expected_renamed=[(old_path, new_path)])
1241
        self.assertContent(branch, revtree1, old_path, "aaa")
1242
        self.assertContent(branch, revtree2, new_path, "bbb")
1243
1244
    def test_rename_then_modify_file_in_new_dir(self):
1245
        handler, branch = self.get_handler()
1246
        old_path = 'd1/a'
1247
        new_path = 'd2/b'
1248
        handler.process(self.get_command_iter(old_path, new_path))
1249
        revtree0, revtree1 = self.assertChanges(branch, 1,
1250
            expected_added=[('d1',), (old_path,)])
1251
        # Note: the delta doesn't show the modification?
1252
        # The actual new content is validated in the assertions following.
1253
        revtree1, revtree2 = self.assertChanges(branch, 2,
1254
            expected_renamed=[(old_path, new_path)],
1255
            expected_added=[('d2',)],
1256
            expected_removed=[('d1',)])
1257
        self.assertContent(branch, revtree1, old_path, "aaa")
1258
        self.assertContent(branch, revtree2, new_path, "bbb")
1259
1260
    def test_rename_then_modify_symlink_in_root(self):
1261
        handler, branch = self.get_handler()
1262
        old_path = 'a'
1263
        new_path = 'b'
1264
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1265
        revtree0, revtree1 = self.assertChanges(branch, 1,
1266
            expected_added=[(old_path,)])
1267
        # Note: the delta doesn't show the modification?
1268
        # The actual new content is validated in the assertions following.
1269
        revtree1, revtree2 = self.assertChanges(branch, 2,
1270
            expected_renamed=[(old_path, new_path)])
1271
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1272
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1273
        self.assertRevisionRoot(revtree1, old_path)
1274
        self.assertRevisionRoot(revtree2, new_path)
1275
1276
    def test_rename_then_modify_symlink_in_subdir(self):
1277
        handler, branch = self.get_handler()
1278
        old_path = 'd/a'
1279
        new_path = 'd/b'
1280
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1281
        revtree0, revtree1 = self.assertChanges(branch, 1,
1282
            expected_added=[('d',), (old_path,)])
1283
        # Note: the delta doesn't show the modification?
1284
        # The actual new content is validated in the assertions following.
1285
        revtree1, revtree2 = self.assertChanges(branch, 2,
1286
            expected_renamed=[(old_path, new_path)])
1287
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1288
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1289
1290
    def test_rename_then_modify_symlink_in_new_dir(self):
1291
        handler, branch = self.get_handler()
1292
        old_path = 'd1/a'
1293
        new_path = 'd2/b'
1294
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1295
        revtree0, revtree1 = self.assertChanges(branch, 1,
1296
            expected_added=[('d1',), (old_path,)])
1297
        # Note: the delta doesn't show the modification?
1298
        # The actual new content is validated in the assertions following.
1299
        revtree1, revtree2 = self.assertChanges(branch, 2,
1300
            expected_renamed=[(old_path, new_path)],
1301
            expected_added=[('d2',)],
1302
            expected_removed=[('d1',)])
1303
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1304
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1305
1306
0.64.233 by Ian Clatworthy
Handle delete, rename then modify all in the one commit
1307
class TestImportToPackDeleteRenameThenModify(TestCaseForGenericProcessor):
1308
    """Test rename of to a deleted path then modfy the new-path in the same commit."""
1309
1310
    def get_command_iter(self, old_path, new_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1311
0.64.233 by Ian Clatworthy
Handle delete, rename then modify all in the one commit
1312
        # Revno 1: create two files or symlinks
1313
        # Revno 2: delete one, rename the other to it then modify the newly created path
1314
        def command_list():
1315
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1316
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1317
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1318
                yield commands.FileModifyCommand(old_path, kind_to_mode(kind, False),
0.64.233 by Ian Clatworthy
Handle delete, rename then modify all in the one commit
1319
                        None, "aaa")
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1320
                yield commands.FileModifyCommand(new_path, kind_to_mode(kind, False),
0.64.233 by Ian Clatworthy
Handle delete, rename then modify all in the one commit
1321
                        None, "zzz")
1322
            yield commands.CommitCommand('head', '1', author,
1323
                committer, "commit 1", None, [], files_one)
1324
            def files_two():
1325
                yield commands.FileDeleteCommand(new_path)
1326
                yield commands.FileRenameCommand(old_path, new_path)
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1327
                yield commands.FileModifyCommand(new_path, kind_to_mode(kind, False),
0.64.233 by Ian Clatworthy
Handle delete, rename then modify all in the one commit
1328
                        None, "bbb")
1329
            yield commands.CommitCommand('head', '2', author,
1330
                committer, "commit 2", ":1", [], files_two)
1331
        return command_list
1332
1333
    def test_delete_rename_then_modify_file_in_root(self):
1334
        handler, branch = self.get_handler()
1335
        old_path = 'a'
1336
        new_path = 'b'
1337
        handler.process(self.get_command_iter(old_path, new_path))
1338
        revtree0, revtree1 = self.assertChanges(branch, 1,
1339
            expected_added=[(old_path,), (new_path,)])
1340
        # Note: the delta doesn't show the modification?
1341
        # The actual new content is validated in the assertions following.
1342
        revtree1, revtree2 = self.assertChanges(branch, 2,
1343
            expected_removed=[(new_path,)],
1344
            expected_renamed=[(old_path, new_path)])
1345
        self.assertContent(branch, revtree1, old_path, "aaa")
1346
        self.assertContent(branch, revtree1, new_path, "zzz")
1347
        self.assertContent(branch, revtree2, new_path, "bbb")
1348
        self.assertRevisionRoot(revtree1, old_path)
1349
        self.assertRevisionRoot(revtree1, new_path)
1350
        self.assertRevisionRoot(revtree2, new_path)
1351
1352
    def test_delete_rename_then_modify_file_in_subdir(self):
1353
        handler, branch = self.get_handler()
1354
        old_path = 'd/a'
1355
        new_path = 'd/b'
1356
        handler.process(self.get_command_iter(old_path, new_path))
1357
        revtree0, revtree1 = self.assertChanges(branch, 1,
1358
            expected_added=[('d',), (old_path,), (new_path,)])
1359
        # Note: the delta doesn't show the modification?
1360
        # The actual new content is validated in the assertions following.
1361
        revtree1, revtree2 = self.assertChanges(branch, 2,
1362
            expected_removed=[(new_path,)],
1363
            expected_renamed=[(old_path, new_path)])
1364
        self.assertContent(branch, revtree1, old_path, "aaa")
1365
        self.assertContent(branch, revtree1, new_path, "zzz")
1366
        self.assertContent(branch, revtree2, new_path, "bbb")
1367
1368
    def test_delete_rename_then_modify_file_in_new_dir(self):
1369
        handler, branch = self.get_handler()
1370
        old_path = 'd1/a'
1371
        new_path = 'd2/b'
1372
        handler.process(self.get_command_iter(old_path, new_path))
1373
        revtree0, revtree1 = self.assertChanges(branch, 1,
1374
            expected_added=[('d1',), ('d2',), (old_path,), (new_path,)])
1375
        # Note: the delta doesn't show the modification?
1376
        # The actual new content is validated in the assertions following.
1377
        revtree1, revtree2 = self.assertChanges(branch, 2,
1378
            expected_removed=[('d1',), (new_path,)],
1379
            expected_renamed=[(old_path, new_path)])
1380
        self.assertContent(branch, revtree1, old_path, "aaa")
1381
        self.assertContent(branch, revtree1, new_path, "zzz")
1382
        self.assertContent(branch, revtree2, new_path, "bbb")
1383
1384
    def test_delete_rename_then_modify_symlink_in_root(self):
1385
        handler, branch = self.get_handler()
1386
        old_path = 'a'
1387
        new_path = 'b'
1388
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1389
        revtree0, revtree1 = self.assertChanges(branch, 1,
1390
            expected_added=[(old_path,), (new_path,)])
1391
        # Note: the delta doesn't show the modification?
1392
        # The actual new content is validated in the assertions following.
1393
        revtree1, revtree2 = self.assertChanges(branch, 2,
1394
            expected_removed=[(new_path,)],
1395
            expected_renamed=[(old_path, new_path)])
1396
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1397
        self.assertSymlinkTarget(branch, revtree1, new_path, "zzz")
1398
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1399
        self.assertRevisionRoot(revtree1, old_path)
1400
        self.assertRevisionRoot(revtree1, new_path)
1401
        self.assertRevisionRoot(revtree2, new_path)
1402
1403
    def test_delete_rename_then_modify_symlink_in_subdir(self):
1404
        handler, branch = self.get_handler()
1405
        old_path = 'd/a'
1406
        new_path = 'd/b'
1407
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1408
        revtree0, revtree1 = self.assertChanges(branch, 1,
1409
            expected_added=[('d',), (old_path,), (new_path,)])
1410
        # Note: the delta doesn't show the modification?
1411
        # The actual new content is validated in the assertions following.
1412
        revtree1, revtree2 = self.assertChanges(branch, 2,
1413
            expected_removed=[(new_path,)],
1414
            expected_renamed=[(old_path, new_path)])
1415
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1416
        self.assertSymlinkTarget(branch, revtree1, new_path, "zzz")
1417
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1418
1419
    def test_delete_rename_then_modify_symlink_in_new_dir(self):
1420
        handler, branch = self.get_handler()
1421
        old_path = 'd1/a'
1422
        new_path = 'd2/b'
1423
        handler.process(self.get_command_iter(old_path, new_path, 'symlink'))
1424
        revtree0, revtree1 = self.assertChanges(branch, 1,
1425
            expected_added=[('d1',), ('d2',), (old_path,), (new_path,)])
1426
        # Note: the delta doesn't show the modification?
1427
        # The actual new content is validated in the assertions following.
1428
        revtree1, revtree2 = self.assertChanges(branch, 2,
1429
            expected_removed=[('d1',), (new_path,)],
1430
            expected_renamed=[(old_path, new_path)])
1431
        self.assertSymlinkTarget(branch, revtree1, old_path, "aaa")
1432
        self.assertSymlinkTarget(branch, revtree1, new_path, "zzz")
1433
        self.assertSymlinkTarget(branch, revtree2, new_path, "bbb")
1434
1435
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
1436
class TestImportToPackRenameTricky(TestCaseForGenericProcessor):
0.80.6 by Ian Clatworthy
file/symlink <-> directory rename tests
1437
1438
    def file_command_iter(self, path1, old_path2, new_path2, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1439
0.80.6 by Ian Clatworthy
file/symlink <-> directory rename tests
1440
        # Revno 1: create two files or symlinks in a directory
1441
        # Revno 2: rename the second file so that it implicitly deletes the
1442
        # first one because either:
1443
        # * the new file is a in directory with the old file name
1444
        # * the new file has the same name as the directory of the first
1445
        def command_list():
1446
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1447
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1448
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1449
                yield commands.FileModifyCommand(path1, kind_to_mode(kind, False),
0.80.6 by Ian Clatworthy
file/symlink <-> directory rename tests
1450
                        None, "aaa")
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1451
                yield commands.FileModifyCommand(old_path2, kind_to_mode(kind, False),
0.80.6 by Ian Clatworthy
file/symlink <-> directory rename tests
1452
                        None, "bbb")
1453
            yield commands.CommitCommand('head', '1', author,
1454
                committer, "commit 1", None, [], files_one)
1455
            def files_two():
1456
                yield commands.FileRenameCommand(old_path2, new_path2)
1457
            yield commands.CommitCommand('head', '2', author,
1458
                committer, "commit 2", ":1", [], files_two)
1459
        return command_list
1460
1461
    def test_rename_file_becomes_directory(self):
1462
        handler, branch = self.get_handler()
1463
        old_path2 = 'foo'
1464
        path1     = 'a/b'
1465
        new_path2 = 'a/b/c'
1466
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
1467
        revtree0, revtree1 = self.assertChanges(branch, 1,
1468
            expected_added=[('a',), (path1,), (old_path2,)])
1469
        revtree1, revtree2 = self.assertChanges(branch, 2,
1470
            expected_renamed=[(old_path2, new_path2)],
1471
            expected_kind_changed=[(path1, 'file', 'directory')])
1472
        self.assertContent(branch, revtree1, path1, "aaa")
1473
        self.assertContent(branch, revtree2, new_path2, "bbb")
1474
1475
    def test_rename_directory_becomes_file(self):
1476
        handler, branch = self.get_handler()
1477
        old_path2 = 'foo'
1478
        path1     = 'a/b/c'
1479
        new_path2 = 'a/b'
1480
        handler.process(self.file_command_iter(path1, old_path2, new_path2))
1481
        revtree0, revtree1 = self.assertChanges(branch, 1,
1482
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
1483
        revtree1, revtree2 = self.assertChanges(branch, 2,
1484
            expected_renamed=[(old_path2, new_path2)],
1485
            expected_removed=[(path1,), (new_path2,)])
1486
        self.assertContent(branch, revtree1, path1, "aaa")
1487
        self.assertContent(branch, revtree2, new_path2, "bbb")
1488
1489
    def test_rename_symlink_becomes_directory(self):
1490
        handler, branch = self.get_handler()
1491
        old_path2 = 'foo'
1492
        path1     = 'a/b'
1493
        new_path2 = 'a/b/c'
1494
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
1495
            'symlink'))
1496
        revtree0, revtree1 = self.assertChanges(branch, 1,
1497
            expected_added=[('a',), (path1,), (old_path2,)])
1498
        revtree1, revtree2 = self.assertChanges(branch, 2,
1499
            expected_renamed=[(old_path2, new_path2)],
1500
            expected_kind_changed=[(path1, 'symlink', 'directory')])
1501
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
1502
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
1503
1504
    def test_rename_directory_becomes_symlink(self):
1505
        handler, branch = self.get_handler()
1506
        old_path2 = 'foo'
1507
        path1     = 'a/b/c'
1508
        new_path2 = 'a/b'
1509
        handler.process(self.file_command_iter(path1, old_path2, new_path2,
1510
            'symlink'))
1511
        revtree0, revtree1 = self.assertChanges(branch, 1,
1512
            expected_added=[('a',), ('a/b',), (path1,), (old_path2,)])
1513
        revtree1, revtree2 = self.assertChanges(branch, 2,
1514
            expected_renamed=[(old_path2, new_path2)],
1515
            expected_removed=[(path1,), (new_path2,)])
1516
        self.assertSymlinkTarget(branch, revtree1, path1, "aaa")
1517
        self.assertSymlinkTarget(branch, revtree2, new_path2, "bbb")
1518
1519
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
1520
class TestImportToPackCopy(TestCaseForGenericProcessor):
0.76.2 by Ian Clatworthy
code & tests for file copying
1521
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1522
    def file_command_iter(self, src_path, dest_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1523
0.80.4 by Ian Clatworthy
file executable off <-> on tests
1524
        # Revno 1: create a file or symlink
1525
        # Revno 2: copy it
0.76.2 by Ian Clatworthy
code & tests for file copying
1526
        def command_list():
1527
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1528
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1529
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1530
                yield commands.FileModifyCommand(src_path, kind_to_mode(kind, False),
0.76.2 by Ian Clatworthy
code & tests for file copying
1531
                        None, "aaa")
1532
            yield commands.CommitCommand('head', '1', author,
1533
                committer, "commit 1", None, [], files_one)
1534
            def files_two():
1535
                yield commands.FileCopyCommand(src_path, dest_path)
1536
            yield commands.CommitCommand('head', '2', author,
1537
                committer, "commit 2", ":1", [], files_two)
1538
        return command_list
1539
1540
    def test_copy_file_in_root(self):
1541
        handler, branch = self.get_handler()
1542
        src_path = 'a'
1543
        dest_path = 'b'
1544
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1545
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
1546
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1547
        self.assertContent(branch, revtree1, src_path, "aaa")
1548
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
1549
        self.assertContent(branch, revtree2, dest_path, "aaa")
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1550
        self.assertRevisionRoot(revtree1, src_path)
1551
        self.assertRevisionRoot(revtree2, dest_path)
0.76.2 by Ian Clatworthy
code & tests for file copying
1552
1553
    def test_copy_file_in_subdir(self):
1554
        handler, branch = self.get_handler()
1555
        src_path = 'a/a'
1556
        dest_path = 'a/b'
1557
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1558
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
1559
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1560
        self.assertContent(branch, revtree1, src_path, "aaa")
1561
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
1562
        self.assertContent(branch, revtree2, dest_path, "aaa")
1563
1564
    def test_copy_file_to_new_dir(self):
1565
        handler, branch = self.get_handler()
1566
        src_path = 'a/a'
1567
        dest_path = 'b/a'
1568
        handler.process(self.file_command_iter(src_path, dest_path))
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1569
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.2 by Ian Clatworthy
code & tests for file copying
1570
            expected_added=[('b',), (dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1571
        self.assertContent(branch, revtree1, src_path, "aaa")
1572
        self.assertContent(branch, revtree2, src_path, "aaa")
0.76.2 by Ian Clatworthy
code & tests for file copying
1573
        self.assertContent(branch, revtree2, dest_path, "aaa")
1574
0.76.3 by Ian Clatworthy
symlink copying tests
1575
    def test_copy_symlink_in_root(self):
1576
        handler, branch = self.get_handler()
1577
        src_path = 'a'
1578
        dest_path = 'b'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1579
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1580
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
1581
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1582
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1583
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
1584
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1585
        self.assertRevisionRoot(revtree1, src_path)
1586
        self.assertRevisionRoot(revtree2, dest_path)
0.76.3 by Ian Clatworthy
symlink copying tests
1587
1588
    def test_copy_symlink_in_subdir(self):
1589
        handler, branch = self.get_handler()
1590
        src_path = 'a/a'
1591
        dest_path = 'a/b'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1592
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1593
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
1594
            expected_added=[(dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1595
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1596
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
1597
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
1598
1599
    def test_copy_symlink_to_new_dir(self):
1600
        handler, branch = self.get_handler()
1601
        src_path = 'a/a'
1602
        dest_path = 'b/a'
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1603
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1604
        revtree1, revtree2 = self.assertChanges(branch, 2,
0.76.3 by Ian Clatworthy
symlink copying tests
1605
            expected_added=[('b',), (dest_path,)])
0.80.1 by Ian Clatworthy
basic units tests for filemodify
1606
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1607
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
0.76.3 by Ian Clatworthy
symlink copying tests
1608
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
1609
0.76.2 by Ian Clatworthy
code & tests for file copying
1610
0.99.8 by Ian Clatworthy
handle copy of a newly added file
1611
class TestImportToPackCopyNew(TestCaseForGenericProcessor):
1612
    """Test copy of a newly added file."""
1613
1614
    def file_command_iter(self, src_path, dest_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1615
0.99.8 by Ian Clatworthy
handle copy of a newly added file
1616
        # Revno 1: create a file or symlink and copy it
1617
        def command_list():
1618
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1619
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1620
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1621
                yield commands.FileModifyCommand(src_path, kind_to_mode(kind, False),
0.99.8 by Ian Clatworthy
handle copy of a newly added file
1622
                        None, "aaa")
1623
                yield commands.FileCopyCommand(src_path, dest_path)
1624
            yield commands.CommitCommand('head', '1', author,
1625
                committer, "commit 1", None, [], files_one)
1626
        return command_list
1627
1628
    def test_copy_new_file_in_root(self):
1629
        handler, branch = self.get_handler()
1630
        src_path = 'a'
1631
        dest_path = 'b'
1632
        handler.process(self.file_command_iter(src_path, dest_path))
1633
        revtree0, revtree1 = self.assertChanges(branch, 1,
1634
            expected_added=[(src_path,), (dest_path,)])
1635
        self.assertContent(branch, revtree1, src_path, "aaa")
1636
        self.assertContent(branch, revtree1, dest_path, "aaa")
1637
        self.assertRevisionRoot(revtree1, src_path)
1638
        self.assertRevisionRoot(revtree1, dest_path)
1639
1640
    def test_copy_new_file_in_subdir(self):
1641
        handler, branch = self.get_handler()
1642
        src_path = 'a/a'
1643
        dest_path = 'a/b'
1644
        handler.process(self.file_command_iter(src_path, dest_path))
1645
        revtree0, revtree1 = self.assertChanges(branch, 1,
1646
            expected_added=[('a',), (src_path,), (dest_path,)])
1647
        self.assertContent(branch, revtree1, src_path, "aaa")
1648
        self.assertContent(branch, revtree1, dest_path, "aaa")
1649
1650
    def test_copy_new_file_to_new_dir(self):
1651
        handler, branch = self.get_handler()
1652
        src_path = 'a/a'
1653
        dest_path = 'b/a'
1654
        handler.process(self.file_command_iter(src_path, dest_path))
1655
        revtree0, revtree1 = self.assertChanges(branch, 1,
1656
            expected_added=[('a',), (src_path,), ('b',), (dest_path,)])
1657
        self.assertContent(branch, revtree1, src_path, "aaa")
1658
        self.assertContent(branch, revtree1, dest_path, "aaa")
1659
1660
    def test_copy_new_symlink_in_root(self):
1661
        handler, branch = self.get_handler()
1662
        src_path = 'a'
1663
        dest_path = 'b'
1664
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1665
        revtree0, revtree1 = self.assertChanges(branch, 1,
1666
            expected_added=[(src_path,), (dest_path,)])
1667
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1668
        self.assertSymlinkTarget(branch, revtree1, dest_path, "aaa")
1669
        self.assertRevisionRoot(revtree1, src_path)
1670
        self.assertRevisionRoot(revtree1, dest_path)
1671
1672
    def test_copy_new_symlink_in_subdir(self):
1673
        handler, branch = self.get_handler()
1674
        src_path = 'a/a'
1675
        dest_path = 'a/b'
1676
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1677
        revtree0, revtree1 = self.assertChanges(branch, 1,
1678
            expected_added=[('a',), (src_path,), (dest_path,)])
1679
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1680
        self.assertSymlinkTarget(branch, revtree1, dest_path, "aaa")
1681
1682
    def test_copy_new_symlink_to_new_dir(self):
1683
        handler, branch = self.get_handler()
1684
        src_path = 'a/a'
1685
        dest_path = 'b/a'
1686
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1687
        revtree0, revtree1 = self.assertChanges(branch, 1,
1688
            expected_added=[('a',), (src_path,), ('b',), (dest_path,)])
1689
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1690
        self.assertSymlinkTarget(branch, revtree1, dest_path, "aaa")
1691
1692
0.99.15 by Ian Clatworthy
Add tests for copying to a path deleted in the same commit
1693
class TestImportToPackCopyToDeleted(TestCaseForGenericProcessor):
1694
1695
    def file_command_iter(self, src_path, dest_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1696
0.99.15 by Ian Clatworthy
Add tests for copying to a path deleted in the same commit
1697
        # Revno 1: create two files or symlinks
1698
        # Revno 2: delete one and copy the other one to its path
1699
        def command_list():
1700
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1701
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1702
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1703
                yield commands.FileModifyCommand(src_path, kind_to_mode(kind, False),
0.99.15 by Ian Clatworthy
Add tests for copying to a path deleted in the same commit
1704
                        None, "aaa")
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1705
                yield commands.FileModifyCommand(dest_path, kind_to_mode(kind, False),
0.99.15 by Ian Clatworthy
Add tests for copying to a path deleted in the same commit
1706
                        None, "bbb")
1707
            yield commands.CommitCommand('head', '1', author,
1708
                committer, "commit 1", None, [], files_one)
1709
            def files_two():
1710
                yield commands.FileDeleteCommand(dest_path)
1711
                yield commands.FileCopyCommand(src_path, dest_path)
1712
            yield commands.CommitCommand('head', '2', author,
1713
                committer, "commit 2", ":1", [], files_two)
1714
        return command_list
1715
1716
    def test_copy_to_deleted_file_in_root(self):
1717
        handler, branch = self.get_handler()
1718
        src_path = 'a'
1719
        dest_path = 'b'
1720
        handler.process(self.file_command_iter(src_path, dest_path))
1721
        revtree0, revtree1 = self.assertChanges(branch, 1,
1722
            expected_added=[(src_path,), (dest_path,)])
1723
        revtree1, revtree2 = self.assertChanges(branch, 2,
1724
            expected_removed=[(dest_path,)],
1725
            expected_added=[(dest_path,)])
1726
        self.assertContent(branch, revtree1, src_path, "aaa")
1727
        self.assertContent(branch, revtree1, dest_path, "bbb")
1728
        self.assertContent(branch, revtree2, src_path, "aaa")
1729
        self.assertContent(branch, revtree2, dest_path, "aaa")
1730
        self.assertRevisionRoot(revtree1, src_path)
1731
        self.assertRevisionRoot(revtree1, dest_path)
1732
1733
    def test_copy_to_deleted_symlink_in_root(self):
1734
        handler, branch = self.get_handler()
1735
        src_path = 'a'
1736
        dest_path = 'b'
1737
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1738
        revtree0, revtree1 = self.assertChanges(branch, 1,
1739
            expected_added=[(src_path,), (dest_path,)])
1740
        revtree1, revtree2 = self.assertChanges(branch, 2,
1741
            expected_removed=[(dest_path,)],
1742
            expected_added=[(dest_path,)])
1743
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1744
        self.assertSymlinkTarget(branch, revtree1, dest_path, "bbb")
1745
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
1746
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
1747
        self.assertRevisionRoot(revtree1, src_path)
1748
        self.assertRevisionRoot(revtree1, dest_path)
1749
1750
    def test_copy_to_deleted_file_in_subdir(self):
1751
        handler, branch = self.get_handler()
1752
        src_path = 'd/a'
1753
        dest_path = 'd/b'
1754
        handler.process(self.file_command_iter(src_path, dest_path))
1755
        revtree0, revtree1 = self.assertChanges(branch, 1,
1756
            expected_added=[('d',), (src_path,), (dest_path,)])
1757
        revtree1, revtree2 = self.assertChanges(branch, 2,
1758
            expected_removed=[(dest_path,)],
1759
            expected_added=[(dest_path,)])
1760
        self.assertContent(branch, revtree1, src_path, "aaa")
1761
        self.assertContent(branch, revtree1, dest_path, "bbb")
1762
        self.assertContent(branch, revtree2, src_path, "aaa")
1763
        self.assertContent(branch, revtree2, dest_path, "aaa")
1764
1765
    def test_copy_to_deleted_symlink_in_subdir(self):
1766
        handler, branch = self.get_handler()
1767
        src_path = 'd/a'
1768
        dest_path = 'd/b'
1769
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1770
        revtree0, revtree1 = self.assertChanges(branch, 1,
1771
            expected_added=[('d',), (src_path,), (dest_path,)])
1772
        revtree1, revtree2 = self.assertChanges(branch, 2,
1773
            expected_removed=[(dest_path,)],
1774
            expected_added=[(dest_path,)])
1775
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1776
        self.assertSymlinkTarget(branch, revtree1, dest_path, "bbb")
1777
        self.assertSymlinkTarget(branch, revtree2, src_path, "aaa")
1778
        self.assertSymlinkTarget(branch, revtree2, dest_path, "aaa")
1779
1780
0.99.18 by Ian Clatworthy
Handle copy of a file/symlink already modified in this commit
1781
class TestImportToPackCopyModified(TestCaseForGenericProcessor):
1782
    """Test copy of file/symlink already modified in this commit."""
1783
1784
    def file_command_iter(self, src_path, dest_path, kind='file'):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1785
0.99.18 by Ian Clatworthy
Handle copy of a file/symlink already modified in this commit
1786
        # Revno 1: create a file or symlink
1787
        # Revno 2: modify and copy it
1788
        def command_list():
1789
            author = ['', 'bugs@a.com', time.time(), time.timezone]
1790
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1791
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1792
                yield commands.FileModifyCommand(src_path, kind_to_mode(kind, False),
0.99.18 by Ian Clatworthy
Handle copy of a file/symlink already modified in this commit
1793
                        None, "aaa")
1794
            yield commands.CommitCommand('head', '1', author,
1795
                committer, "commit 1", None, [], files_one)
1796
            def files_two():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1797
                yield commands.FileModifyCommand(src_path, kind_to_mode(kind, False),
0.99.18 by Ian Clatworthy
Handle copy of a file/symlink already modified in this commit
1798
                        None, "bbb")
1799
                yield commands.FileCopyCommand(src_path, dest_path)
1800
            yield commands.CommitCommand('head', '2', author,
1801
                committer, "commit 2", ":1", [], files_two)
1802
        return command_list
1803
1804
    def test_copy_of_modified_file_in_root(self):
1805
        handler, branch = self.get_handler()
1806
        src_path = 'a'
1807
        dest_path = 'b'
1808
        handler.process(self.file_command_iter(src_path, dest_path))
1809
        revtree1, revtree2 = self.assertChanges(branch, 2,
1810
            expected_modified=[(src_path,)],
1811
            expected_added=[(dest_path,)])
1812
        self.assertContent(branch, revtree1, src_path, "aaa")
1813
        self.assertContent(branch, revtree2, src_path, "bbb")
1814
        self.assertContent(branch, revtree2, dest_path, "bbb")
1815
        self.assertRevisionRoot(revtree1, src_path)
1816
        self.assertRevisionRoot(revtree2, dest_path)
1817
1818
    def test_copy_of_modified_file_in_subdir(self):
1819
        handler, branch = self.get_handler()
1820
        src_path = 'd/a'
1821
        dest_path = 'd/b'
1822
        handler.process(self.file_command_iter(src_path, dest_path))
1823
        revtree1, revtree2 = self.assertChanges(branch, 2,
1824
            expected_modified=[(src_path,)],
1825
            expected_added=[(dest_path,)])
1826
        self.assertContent(branch, revtree1, src_path, "aaa")
1827
        self.assertContent(branch, revtree2, src_path, "bbb")
1828
        self.assertContent(branch, revtree2, dest_path, "bbb")
1829
1830
    def test_copy_of_modified_file_to_new_dir(self):
1831
        handler, branch = self.get_handler()
1832
        src_path = 'd1/a'
1833
        dest_path = 'd2/a'
1834
        handler.process(self.file_command_iter(src_path, dest_path))
1835
        revtree1, revtree2 = self.assertChanges(branch, 2,
1836
            expected_modified=[(src_path,)],
1837
            expected_added=[('d2',), (dest_path,)])
1838
        self.assertContent(branch, revtree1, src_path, "aaa")
1839
        self.assertContent(branch, revtree2, src_path, "bbb")
1840
        self.assertContent(branch, revtree2, dest_path, "bbb")
1841
1842
    def test_copy_of_modified_symlink_in_root(self):
1843
        handler, branch = self.get_handler()
1844
        src_path = 'a'
1845
        dest_path = 'b'
1846
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1847
        revtree1, revtree2 = self.assertChanges(branch, 2,
1848
            expected_modified=[(src_path,)],
1849
            expected_added=[(dest_path,)])
1850
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1851
        self.assertSymlinkTarget(branch, revtree2, src_path, "bbb")
1852
        self.assertSymlinkTarget(branch, revtree2, dest_path, "bbb")
1853
        self.assertRevisionRoot(revtree1, src_path)
1854
        self.assertRevisionRoot(revtree2, dest_path)
1855
1856
    def test_copy_of_modified_symlink_in_subdir(self):
1857
        handler, branch = self.get_handler()
1858
        src_path = 'd/a'
1859
        dest_path = 'd/b'
1860
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1861
        revtree1, revtree2 = self.assertChanges(branch, 2,
1862
            expected_modified=[(src_path,)],
1863
            expected_added=[(dest_path,)])
1864
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1865
        self.assertSymlinkTarget(branch, revtree2, src_path, "bbb")
1866
        self.assertSymlinkTarget(branch, revtree2, dest_path, "bbb")
1867
1868
    def test_copy_of_modified_symlink_to_new_dir(self):
1869
        handler, branch = self.get_handler()
1870
        src_path = 'd1/a'
1871
        dest_path = 'd2/a'
1872
        handler.process(self.file_command_iter(src_path, dest_path, 'symlink'))
1873
        revtree1, revtree2 = self.assertChanges(branch, 2,
1874
            expected_modified=[(src_path,)],
1875
            expected_added=[('d2',), (dest_path,)])
1876
        self.assertSymlinkTarget(branch, revtree1, src_path, "aaa")
1877
        self.assertSymlinkTarget(branch, revtree2, src_path, "bbb")
1878
        self.assertSymlinkTarget(branch, revtree2, dest_path, "bbb")
0.99.10 by Ian Clatworthy
commented out draft of CopyModified tests
1879
1880
0.85.1 by Ian Clatworthy
extend tests to test the chk code path
1881
class TestImportToPackFileKinds(TestCaseForGenericProcessor):
0.64.74 by Ian Clatworthy
fix symlink importing
1882
1883
    def get_command_iter(self, path, kind, content):
0.123.13 by Jelmer Vernooij
Check for availability of fastimport before running tests.
1884
0.64.74 by Ian Clatworthy
fix symlink importing
1885
        def command_list():
1886
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1887
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1888
                yield commands.FileModifyCommand(path, kind_to_mode(kind, False),
0.64.74 by Ian Clatworthy
fix symlink importing
1889
                        None, content)
1890
            yield commands.CommitCommand('head', '1', None,
1891
                committer, "commit 1", None, [], files_one)
1892
        return command_list
1893
1894
    def test_import_plainfile(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
1895
        handler, branch = self.get_handler()
1896
        handler.process(self.get_command_iter('foo', 'file', 'aaa'))
0.64.74 by Ian Clatworthy
fix symlink importing
1897
1898
    def test_import_symlink(self):
0.76.1 by Ian Clatworthy
clean-up tests for GenericProcessor
1899
        handler, branch = self.get_handler()
1900
        handler.process(self.get_command_iter('foo', 'symlink', 'bar'))
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1901
1902
1903
class TestModifyRevertInBranch(TestCaseForGenericProcessor):
1904
1905
    def file_command_iter(self):
1906
        # A     add 'foo'
1907
        # |\
1908
        # | B   modify 'foo'
1909
        # | |
1910
        # | C   revert 'foo' back to A
1911
        # |/
1912
        # D     merge 'foo'
1913
        def command_list():
0.115.4 by John Arbash Meinel
(broken) Start working towards using CommitBuilder rather than using a custom implementation.
1914
            committer_a = ['', 'a@elmer.com', time.time(), time.timezone]
1915
            committer_b = ['', 'b@elmer.com', time.time(), time.timezone]
1916
            committer_c = ['', 'c@elmer.com', time.time(), time.timezone]
1917
            committer_d = ['', 'd@elmer.com', time.time(), time.timezone]
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1918
            def files_one():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1919
                yield commands.FileModifyCommand('foo', kind_to_mode('file', False),
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1920
                        None, "content A\n")
1921
            yield commands.CommitCommand('head', '1', None,
1922
                committer_a, "commit 1", None, [], files_one)
1923
            def files_two():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1924
                yield commands.FileModifyCommand('foo', kind_to_mode('file', False),
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1925
                        None, "content B\n")
1926
            yield commands.CommitCommand('head', '2', None,
1927
                committer_b, "commit 2", ":1", [], files_two)
1928
            def files_three():
0.123.8 by Jelmer Vernooij
Use modes for FileModifyCommand.
1929
                yield commands.FileModifyCommand('foo', kind_to_mode('file', False),
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1930
                        None, "content A\n")
1931
            yield commands.CommitCommand('head', '3', None,
1932
                committer_c, "commit 3", ":2", [], files_three)
1933
            yield commands.CommitCommand('head', '4', None,
0.115.4 by John Arbash Meinel
(broken) Start working towards using CommitBuilder rather than using a custom implementation.
1934
                committer_d, "commit 4", ":1", [':3'], lambda: [])
0.115.3 by John Arbash Meinel
add the failing test that we preserve the last-modified revision
1935
        return command_list
1936
1937
    def test_modify_revert(self):
1938
        handler, branch = self.get_handler()
1939
        handler.process(self.file_command_iter())
0.115.4 by John Arbash Meinel
(broken) Start working towards using CommitBuilder rather than using a custom implementation.
1940
        branch.lock_read()
1941
        self.addCleanup(branch.unlock)
1942
        rev_d = branch.last_revision()
1943
        rev_a, rev_c = branch.repository.get_parent_map([rev_d])[rev_d]
1944
        rev_b = branch.repository.get_parent_map([rev_c])[rev_c][0]
1945
        rtree_a, rtree_b, rtree_c, rtree_d = branch.repository.revision_trees([
1946
            rev_a, rev_b, rev_c, rev_d])
1947
        foo_id = rtree_a.path2id('foo')
1948
        self.assertEqual(rev_a, rtree_a.inventory[foo_id].revision)
1949
        self.assertEqual(rev_b, rtree_b.inventory[foo_id].revision)
1950
        self.assertEqual(rev_c, rtree_c.inventory[foo_id].revision)
1951
        self.assertEqual(rev_c, rtree_d.inventory[foo_id].revision)
0.64.303 by Jelmer Vernooij
Cope with non-utf8 characters in commit messages.
1952
1953
1954
class TestCommitCommands(TestCaseForGenericProcessor):
1955
1956
    def test_non_utf8_commit_message(self):
1957
        handler, branch = self.get_handler()
1958
        def files_one():
1959
            yield commands.FileModifyCommand('a',
1960
                kind_to_mode('file', False), None, "data")
1961
        def command_list():
1962
            committer = ['', 'elmer@a.com', time.time(), time.timezone]
1963
            yield commands.CommitCommand('head', '1', None,
1964
                committer, 'This is a funky character: \x83', None, [],
1965
                files_one)
1966
        handler.process(command_list)
1967
        rev = branch.repository.get_revision(branch.last_revision())
1968
        self.assertEquals(u"This is a funky character: \ufffd", rev.message)
0.64.332 by Jelmer Vernooij
Cope with non-utf8 characters in paths when importing.
1969
1970
1971
class TestAddNonUtf8InBranch(TestCaseForGenericProcessor):
1972
1973
    def file_command_iter(self):
1974
        # A     add 'foo\x83'
1975
        def command_list():
1976
            committer_a = ['', 'a@elmer.com', time.time(), time.timezone]
1977
            def files_one():
1978
                yield commands.FileModifyCommand(
1979
                    'foo\x83', kind_to_mode('file', False), None, "content A\n")
1980
            yield commands.CommitCommand('head', '1', None,
1981
                committer_a, "commit 1", None, [], files_one)
1982
        return command_list
1983
1984
    def test_add(self):
1985
        handler, branch = self.get_handler()
1986
        handler.process(self.file_command_iter())
1987
        branch.lock_read()
1988
        self.addCleanup(branch.unlock)
1989
        rev_a = branch.last_revision()
1990
        rtree_a = branch.repository.revision_tree(rev_a)
1991
        foo_id = rtree_a.path2id(u'foo\ufffd')
1992
        self.assertEqual(rev_a, rtree_a.inventory[foo_id].revision)