/brz/remove-bazaar

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