/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
1
import os
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
2
import shutil
3
import tempfile
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
4
import unittest
1185.12.36 by abentley
Removed all remaining use of readonly_path
5
import stat
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
6
import sys
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
7
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
8
from bzrlib.selftest import TestCaseInTempDir, TestCase
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
9
from bzrlib.branch import ScratchBranch, Branch
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
10
from bzrlib.errors import (NotBranchError, NotVersionedError,
1185.12.87 by Aaron Bentley
Updated NEWS, error out if --show-base supplied and unsupported
11
                           WorkingTreeNotRevision, BzrCommandError)
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
12
from bzrlib.inventory import RootEntry
13
import bzrlib.inventory as inventory
1185.12.31 by Aaron Bentley
Replaced FileCreate with TreeFileCreate, fixed revert with empty parents
14
from bzrlib.osutils import file_kind, rename, sha_file
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
15
from bzrlib import changeset
16
from bzrlib.merge_core import (ApplyMerge3, make_merge_changeset,
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
17
                               BackupBeforeChange, ExecFlagMerge, WeaveMerge)
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
18
from bzrlib.changeset import Inventory, apply_changeset, invert_dict, \
19
    get_contents, ReplaceContents, ChangeExecFlag
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
20
from bzrlib.clone import copy_branch
21
from bzrlib.merge import merge
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
22
from bzrlib.workingtree import WorkingTree
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
23
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
24
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
25
class FalseTree(object):
26
    def __init__(self, realtree):
27
        self._realtree = realtree
28
        self.inventory = self
29
30
    def __getitem__(self, file_id):
31
        entry = self.make_inventory_entry(file_id)
32
        if entry is None:
33
            raise KeyError(file_id)
34
        return entry
35
        
36
    def make_inventory_entry(self, file_id):
1185.12.40 by abentley
Got even closer to standard Tree interface
37
        path = self._realtree.inventory_dict.get(file_id)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
38
        if path is None:
39
            return None
40
        if path == "":
41
            return RootEntry(file_id)
42
        dir, name = os.path.split(path)
43
        kind = file_kind(self._realtree.abs_path(path))
1185.12.40 by abentley
Got even closer to standard Tree interface
44
        for parent_id, path in self._realtree.inventory_dict.iteritems():
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
45
            if path == dir:
46
                break
47
        if path != dir:
48
            raise Exception("Can't find parent for %s" % name)
1399.1.10 by Robert Collins
remove kind from the InventoryEntry constructor - only child classes should be created now
49
        if kind not in ('directory', 'file', 'symlink'):
50
            raise ValueError('unknown kind %r' % kind)
51
        if kind == 'directory':
52
            return inventory.InventoryDirectory(file_id, name, parent_id)
53
        elif kind == 'file':
54
            return inventory.InventoryFile(file_id, name, parent_id)
55
        else:
56
            return inventory.InventoryLink(file_id, name, parent_id)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
57
58
59
class MergeTree(object):
60
    def __init__(self, dir):
61
        self.dir = dir;
62
        os.mkdir(dir)
1185.12.40 by abentley
Got even closer to standard Tree interface
63
        self.inventory_dict = {'0': ""}
64
        self.inventory = FalseTree(self)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
65
    
66
    def child_path(self, parent, name):
1185.12.40 by abentley
Got even closer to standard Tree interface
67
        return os.path.join(self.inventory_dict[parent], name)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
68
69
    def add_file(self, id, parent, name, contents, mode):
70
        path = self.child_path(parent, name)
71
        full_path = self.abs_path(path)
72
        assert not os.path.exists(full_path)
73
        file(full_path, "wb").write(contents)
74
        os.chmod(self.abs_path(path), mode)
1185.12.40 by abentley
Got even closer to standard Tree interface
75
        self.inventory_dict[id] = path
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
76
1185.12.34 by Aaron Bentley
Added symlink three-way tests
77
    def add_symlink(self, id, parent, name, target):
78
        path = self.child_path(parent, name)
79
        full_path = self.abs_path(path)
80
        assert not os.path.exists(full_path)
81
        os.symlink(target, full_path)
1185.12.40 by abentley
Got even closer to standard Tree interface
82
        self.inventory_dict[id] = path
1185.12.34 by Aaron Bentley
Added symlink three-way tests
83
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
84
    def remove_file(self, id):
85
        os.unlink(self.full_path(id))
1185.12.40 by abentley
Got even closer to standard Tree interface
86
        del self.inventory_dict[id]
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
87
88
    def add_dir(self, id, parent, name, mode):
89
        path = self.child_path(parent, name)
90
        full_path = self.abs_path(path)
91
        assert not os.path.exists(full_path)
92
        os.mkdir(self.abs_path(path))
93
        os.chmod(self.abs_path(path), mode)
1185.12.40 by abentley
Got even closer to standard Tree interface
94
        self.inventory_dict[id] = path
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
95
96
    def abs_path(self, path):
97
        return os.path.join(self.dir, path)
98
99
    def full_path(self, id):
100
        try:
1185.12.40 by abentley
Got even closer to standard Tree interface
101
            tree_path = self.inventory_dict[id]
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
102
        except KeyError:
103
            return None
104
        return self.abs_path(tree_path)
105
106
    def readonly_path(self, id):
107
        return self.full_path(id)
108
109
    def __contains__(self, file_id):
1185.12.40 by abentley
Got even closer to standard Tree interface
110
        return file_id in self.inventory_dict
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
111
1185.12.39 by abentley
Propogated has_or_had_id to Tree
112
    def has_or_had_id(self, file_id):
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
113
        return file_id in self
114
115
    def get_file(self, file_id):
1185.12.36 by abentley
Removed all remaining use of readonly_path
116
        path = self.full_path(file_id)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
117
        return file(path, "rb")
118
119
    def id2path(self, file_id):
1185.12.40 by abentley
Got even closer to standard Tree interface
120
        return self.inventory_dict[file_id]
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
121
1185.12.36 by abentley
Removed all remaining use of readonly_path
122
    def id2abspath(self, id):
123
        return self.full_path(id)
124
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
125
    def change_path(self, id, path):
1185.12.40 by abentley
Got even closer to standard Tree interface
126
        old_path = os.path.join(self.dir, self.inventory_dict[id])
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
127
        rename(old_path, self.abs_path(path))
1185.12.40 by abentley
Got even closer to standard Tree interface
128
        self.inventory_dict[id] = path
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
129
1185.12.28 by Aaron Bentley
Removed use of readonly path for executability test
130
    def is_executable(self, file_id):
131
        mode = os.lstat(self.full_path(file_id)).st_mode
1185.12.36 by abentley
Removed all remaining use of readonly_path
132
        return bool(stat.S_ISREG(mode) and stat.S_IEXEC & mode)
1185.12.28 by Aaron Bentley
Removed use of readonly path for executability test
133
134
    def kind(self, file_id):
1185.12.30 by Aaron Bentley
Moved all fooCreate into get_contents
135
        return file_kind(self.full_path(file_id))
1185.12.28 by Aaron Bentley
Removed use of readonly path for executability test
136
1185.12.29 by Aaron Bentley
Removed readonly_path from changeset generation
137
    def get_symlink_target(self, file_id):
138
        return os.readlink(self.full_path(file_id))
139
1185.12.31 by Aaron Bentley
Replaced FileCreate with TreeFileCreate, fixed revert with empty parents
140
    def get_file_sha1(self, file_id):
141
        return sha_file(file(self.full_path(file_id), "rb"))
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
142
143
class MergeBuilder(object):
144
    def __init__(self):
145
        self.dir = tempfile.mkdtemp(prefix="BaZing")
146
        self.base = MergeTree(os.path.join(self.dir, "base"))
147
        self.this = MergeTree(os.path.join(self.dir, "this"))
148
        self.other = MergeTree(os.path.join(self.dir, "other"))
149
        
150
        self.cset = changeset.Changeset()
151
        self.cset.add_entry(changeset.ChangesetEntry("0", 
152
                                                     changeset.NULL_ID, "./."))
153
    def get_cset_path(self, parent, name):
154
        if name is None:
155
            assert (parent is None)
156
            return None
157
        return os.path.join(self.cset.entries[parent].path, name)
158
159
    def add_file(self, id, parent, name, contents, mode):
160
        self.base.add_file(id, parent, name, contents, mode)
161
        self.this.add_file(id, parent, name, contents, mode)
162
        self.other.add_file(id, parent, name, contents, mode)
163
        path = self.get_cset_path(parent, name)
164
        self.cset.add_entry(changeset.ChangesetEntry(id, parent, path))
165
1185.12.34 by Aaron Bentley
Added symlink three-way tests
166
    def add_symlink(self, id, parent, name, contents):
167
        self.base.add_symlink(id, parent, name, contents)
168
        self.this.add_symlink(id, parent, name, contents)
169
        self.other.add_symlink(id, parent, name, contents)
170
        path = self.get_cset_path(parent, name)
171
        self.cset.add_entry(changeset.ChangesetEntry(id, parent, path))
172
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
173
    def remove_file(self, id, base=False, this=False, other=False):
174
        for option, tree in ((base, self.base), (this, self.this), 
175
                             (other, self.other)):
176
            if option:
177
                tree.remove_file(id)
178
            if other or base:
179
                change = self.cset.entries[id].contents_change
180
                if change is None:
181
                    change = changeset.ReplaceContents(None, None)
182
                    self.cset.entries[id].contents_change = change
183
                    def create_file(tree):
1185.12.31 by Aaron Bentley
Replaced FileCreate with TreeFileCreate, fixed revert with empty parents
184
                        return changeset.TreeFileCreate(tree, id)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
185
                    if not other:
186
                        change.new_contents = create_file(self.other)
187
                    if not base:
188
                        change.old_contents = create_file(self.base)
189
                else:
190
                    assert isinstance(change, changeset.ReplaceContents)
191
                if other:
192
                    change.new_contents=None
193
                if base:
194
                    change.old_contents=None
195
                if change.old_contents is None and change.new_contents is None:
196
                    change = None
197
198
    def add_dir(self, id, parent, name, mode):
199
        path = self.get_cset_path(parent, name)
200
        self.base.add_dir(id, parent, name, mode)
201
        self.cset.add_entry(changeset.ChangesetEntry(id, parent, path))
202
        self.this.add_dir(id, parent, name, mode)
203
        self.other.add_dir(id, parent, name, mode)
204
205
    def change_name(self, id, base=None, this=None, other=None):
206
        if base is not None:
207
            self.change_name_tree(id, self.base, base)
208
            self.cset.entries[id].name = base
209
210
        if this is not None:
211
            self.change_name_tree(id, self.this, this)
212
213
        if other is not None:
214
            self.change_name_tree(id, self.other, other)
215
            self.cset.entries[id].new_name = other
216
217
    def change_parent(self, id, base=None, this=None, other=None):
218
        if base is not None:
219
            self.change_parent_tree(id, self.base, base)
220
            self.cset.entries[id].parent = base
221
            self.cset.entries[id].dir = self.cset.entries[base].path
222
223
        if this is not None:
224
            self.change_parent_tree(id, self.this, this)
225
226
        if other is not None:
227
            self.change_parent_tree(id, self.other, other)
228
            self.cset.entries[id].new_parent = other
229
            self.cset.entries[id].new_dir = \
230
                self.cset.entries[other].new_path
231
232
    def change_contents(self, id, base=None, this=None, other=None):
233
        if base is not None:
234
            self.change_contents_tree(id, self.base, base)
235
236
        if this is not None:
237
            self.change_contents_tree(id, self.this, this)
238
239
        if other is not None:
240
            self.change_contents_tree(id, self.other, other)
241
242
        if base is not None or other is not None:
243
            old_contents = file(self.base.full_path(id)).read()
244
            new_contents = file(self.other.full_path(id)).read()
1185.12.31 by Aaron Bentley
Replaced FileCreate with TreeFileCreate, fixed revert with empty parents
245
            contents = changeset.ReplaceFileContents(self.base, self.other, id)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
246
            self.cset.entries[id].contents_change = contents
247
1185.12.34 by Aaron Bentley
Added symlink three-way tests
248
    def change_target(self, id, base=None, this=None, other=None):
249
        if base is not None:
250
            self.change_target_tree(id, self.base, base)
251
252
        if this is not None:
253
            self.change_target_tree(id, self.this, this)
254
255
        if other is not None:
256
            self.change_target_tree(id, self.other, other)
257
258
        if base is not None or other is not None:
259
            old_contents = get_contents(self.base, id)
260
            new_contents = get_contents(self.other, id)
261
            contents = ReplaceContents(old_contents, new_contents)
262
            self.cset.entries[id].contents_change = contents
263
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
264
    def change_perms(self, id, base=None, this=None, other=None):
265
        if base is not None:
266
            self.change_perms_tree(id, self.base, base)
267
268
        if this is not None:
269
            self.change_perms_tree(id, self.this, this)
270
271
        if other is not None:
272
            self.change_perms_tree(id, self.other, other)
273
274
        if base is not None or other is not None:
1185.12.36 by abentley
Removed all remaining use of readonly_path
275
            old_exec = self.base.is_executable(id)
276
            new_exec = self.other.is_executable(id)
1434 by Robert Collins
merge Gustavos executable2 patch
277
            metadata = changeset.ChangeExecFlag(old_exec, new_exec)
278
            self.cset.entries[id].metadata_change = metadata
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
279
280
    def change_name_tree(self, id, tree, name):
281
        new_path = tree.child_path(self.cset.entries[id].parent, name)
282
        tree.change_path(id, new_path)
283
284
    def change_parent_tree(self, id, tree, parent):
285
        new_path = tree.child_path(parent, self.cset.entries[id].name)
286
        tree.change_path(id, new_path)
287
288
    def change_contents_tree(self, id, tree, contents):
289
        path = tree.full_path(id)
290
        mode = os.stat(path).st_mode
291
        file(path, "w").write(contents)
292
        os.chmod(path, mode)
293
1185.12.34 by Aaron Bentley
Added symlink three-way tests
294
    def change_target_tree(self, id, tree, target):
295
        path = tree.full_path(id)
296
        os.unlink(path)
297
        os.symlink(target, path)
298
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
299
    def change_perms_tree(self, id, tree, mode):
300
        os.chmod(tree.full_path(id), mode)
301
302
    def merge_changeset(self, merge_factory):
974.1.83 by Aaron Bentley
Removed unused dir parameter from ExceptionConflictHandler
303
        conflict_handler = changeset.ExceptionConflictHandler()
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
304
        return make_merge_changeset(self.cset, self.this, self.base,
305
                                    self.other, conflict_handler,
306
                                    merge_factory)
307
308
    def apply_inv_change(self, inventory_change, orig_inventory):
309
        orig_inventory_by_path = {}
310
        for file_id, path in orig_inventory.iteritems():
311
            orig_inventory_by_path[path] = file_id
312
313
        def parent_id(file_id):
314
            try:
315
                parent_dir = os.path.dirname(orig_inventory[file_id])
316
            except:
317
                print file_id
318
                raise
319
            if parent_dir == "":
320
                return None
321
            return orig_inventory_by_path[parent_dir]
322
        
323
        def new_path(file_id):
324
            if inventory_change.has_key(file_id):
325
                return inventory_change[file_id]
326
            else:
327
                parent = parent_id(file_id)
328
                if parent is None:
329
                    return orig_inventory[file_id]
330
                dirname = new_path(parent)
331
                return os.path.join(dirname, orig_inventory[file_id])
332
333
        new_inventory = {}
334
        for file_id in orig_inventory.iterkeys():
335
            path = new_path(file_id)
336
            if path is None:
337
                continue
338
            new_inventory[file_id] = path
339
340
        for file_id, path in inventory_change.iteritems():
341
            if orig_inventory.has_key(file_id):
342
                continue
343
            new_inventory[file_id] = path
344
        return new_inventory
345
346
    def apply_changeset(self, cset, conflict_handler=None, reverse=False):
347
        inventory_change = changeset.apply_changeset(cset,
1185.12.40 by abentley
Got even closer to standard Tree interface
348
                                                     self.this.inventory_dict,
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
349
                                                     self.this.dir,
350
                                                     conflict_handler, reverse)
1185.12.40 by abentley
Got even closer to standard Tree interface
351
        self.this.inventory_dict =  self.apply_inv_change(inventory_change, 
352
                                                     self.this.inventory_dict)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
353
354
    def cleanup(self):
355
        shutil.rmtree(self.dir)
356
1448 by Robert Collins
revert symlinks correctly
357
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
358
class MergeTest(unittest.TestCase):
359
    def test_change_name(self):
360
        """Test renames"""
361
        builder = MergeBuilder()
362
        builder.add_file("1", "0", "name1", "hello1", 0755)
363
        builder.change_name("1", other="name2")
364
        builder.add_file("2", "0", "name3", "hello2", 0755)
365
        builder.change_name("2", base="name4")
366
        builder.add_file("3", "0", "name5", "hello3", 0755)
367
        builder.change_name("3", this="name6")
368
        cset = builder.merge_changeset(ApplyMerge3)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
369
        self.assert_(cset.entries["2"].is_boring())
370
        self.assert_(cset.entries["1"].name == "name1")
371
        self.assert_(cset.entries["1"].new_name == "name2")
372
        self.assert_(cset.entries["3"].is_boring())
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
373
        for tree in (builder.this, builder.other, builder.base):
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
374
            self.assert_(tree.dir != builder.dir and 
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
375
                   tree.dir.startswith(builder.dir))
1185.12.40 by abentley
Got even closer to standard Tree interface
376
            for path in tree.inventory_dict.itervalues():
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
377
                fullpath = tree.abs_path(path)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
378
                self.assert_(fullpath.startswith(tree.dir))
379
                self.assert_(not path.startswith(tree.dir))
380
                self.assert_(os.path.exists(fullpath))
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
381
        builder.apply_changeset(cset)
382
        builder.cleanup()
383
        builder = MergeBuilder()
384
        builder.add_file("1", "0", "name1", "hello1", 0644)
385
        builder.change_name("1", other="name2", this="name3")
386
        self.assertRaises(changeset.RenameConflict, 
387
                          builder.merge_changeset, ApplyMerge3)
388
        builder.cleanup()
389
        
390
    def test_file_moves(self):
391
        """Test moves"""
392
        builder = MergeBuilder()
393
        builder.add_dir("1", "0", "dir1", 0755)
394
        builder.add_dir("2", "0", "dir2", 0755)
395
        builder.add_file("3", "1", "file1", "hello1", 0644)
396
        builder.add_file("4", "1", "file2", "hello2", 0644)
397
        builder.add_file("5", "1", "file3", "hello3", 0644)
398
        builder.change_parent("3", other="2")
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
399
        self.assert_(Inventory(builder.other.inventory_dict).get_parent("3") == "2")
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
400
        builder.change_parent("4", this="2")
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
401
        self.assert_(Inventory(builder.this.inventory_dict).get_parent("4") == "2")
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
402
        builder.change_parent("5", base="2")
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
403
        self.assert_(Inventory(builder.base.inventory_dict).get_parent("5") == "2")
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
404
        cset = builder.merge_changeset(ApplyMerge3)
405
        for id in ("1", "2", "4", "5"):
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
406
            self.assert_(cset.entries[id].is_boring())
407
        self.assert_(cset.entries["3"].parent == "1")
408
        self.assert_(cset.entries["3"].new_parent == "2")
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
409
        builder.apply_changeset(cset)
410
        builder.cleanup()
411
412
        builder = MergeBuilder()
413
        builder.add_dir("1", "0", "dir1", 0755)
414
        builder.add_dir("2", "0", "dir2", 0755)
415
        builder.add_dir("3", "0", "dir3", 0755)
416
        builder.add_file("4", "1", "file1", "hello1", 0644)
417
        builder.change_parent("4", other="2", this="3")
418
        self.assertRaises(changeset.MoveConflict, 
419
                          builder.merge_changeset, ApplyMerge3)
420
        builder.cleanup()
421
422
    def test_contents_merge(self):
423
        """Test merge3 merging"""
424
        self.do_contents_test(ApplyMerge3)
425
426
    def test_contents_merge2(self):
427
        """Test diff3 merging"""
428
        self.do_contents_test(changeset.Diff3Merge)
429
430
    def test_contents_merge3(self):
431
        """Test diff3 merging"""
432
        def backup_merge(file_id, base, other):
433
            return BackupBeforeChange(ApplyMerge3(file_id, base, other))
434
        builder = self.contents_test_success(backup_merge)
435
        def backup_exists(file_id):
436
            return os.path.exists(builder.this.full_path(file_id)+"~")
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
437
        self.assert_(backup_exists("1"))
438
        self.assert_(backup_exists("2"))
439
        self.assert_(not backup_exists("3"))
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
440
        builder.cleanup()
441
442
    def do_contents_test(self, merge_factory):
443
        """Test merging with specified ContentsChange factory"""
444
        builder = self.contents_test_success(merge_factory)
445
        builder.cleanup()
446
        self.contents_test_conflicts(merge_factory)
447
448
    def contents_test_success(self, merge_factory):
449
        from inspect import isclass
450
        builder = MergeBuilder()
451
        builder.add_file("1", "0", "name1", "text1", 0755)
452
        builder.change_contents("1", other="text4")
453
        builder.add_file("2", "0", "name3", "text2", 0655)
454
        builder.change_contents("2", base="text5")
455
        builder.add_file("3", "0", "name5", "text3", 0744)
456
        builder.add_file("4", "0", "name6", "text4", 0744)
457
        builder.remove_file("4", base=True)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
458
        self.assert_(not builder.cset.entries["4"].is_boring())
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
459
        builder.change_contents("3", this="text6")
460
        cset = builder.merge_changeset(merge_factory)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
461
        self.assert_(cset.entries["1"].contents_change is not None)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
462
        if isclass(merge_factory):
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
463
            self.assert_(isinstance(cset.entries["1"].contents_change,
464
                          merge_factory))
465
            self.assert_(isinstance(cset.entries["2"].contents_change,
466
                          merge_factory))
467
        self.assert_(cset.entries["3"].is_boring())
468
        self.assert_(cset.entries["4"].is_boring())
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
469
        builder.apply_changeset(cset)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
470
        self.assert_(file(builder.this.full_path("1"), "rb").read() == "text4" )
471
        self.assert_(file(builder.this.full_path("2"), "rb").read() == "text2" )
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
472
        if sys.platform != "win32":
1185.39.1 by Alexey Shamrin
merge forgotten win32 fixes from http://bzr.arbash-meinel.com/branches/bzr/win32/
473
            self.assert_(os.stat(builder.this.full_path("1")).st_mode &0777 == 0755)
474
            self.assert_(os.stat(builder.this.full_path("2")).st_mode &0777 == 0655)
475
            self.assert_(os.stat(builder.this.full_path("3")).st_mode &0777 == 0744)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
476
        return builder
477
478
    def contents_test_conflicts(self, merge_factory):
479
        builder = MergeBuilder()
480
        builder.add_file("1", "0", "name1", "text1", 0755)
481
        builder.change_contents("1", other="text4", this="text3")
482
        cset = builder.merge_changeset(merge_factory)
483
        self.assertRaises(changeset.MergeConflict, builder.apply_changeset,
484
                          cset)
485
        builder.cleanup()
486
1185.12.34 by Aaron Bentley
Added symlink three-way tests
487
    def test_symlink_conflicts(self):
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
488
        if sys.platform != "win32":
489
            builder = MergeBuilder()
490
            builder.add_symlink("2", "0", "name2", "target1")
491
            builder.change_target("2", other="target4", base="text3")
492
            self.assertRaises(changeset.ThreewayContentsConflict,
493
                              builder.merge_changeset, ApplyMerge3)
494
            builder.cleanup()
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
495
1185.12.34 by Aaron Bentley
Added symlink three-way tests
496
    def test_symlink_merge(self):
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
497
        if sys.platform != "win32":
498
            builder = MergeBuilder()
499
            builder.add_symlink("1", "0", "name1", "target1")
500
            builder.add_symlink("2", "0", "name2", "target1")
501
            builder.add_symlink("3", "0", "name3", "target1")
502
            builder.change_target("1", this="target2")
503
            builder.change_target("2", base="target2")
504
            builder.change_target("3", other="target2")
1185.39.1 by Alexey Shamrin
merge forgotten win32 fixes from http://bzr.arbash-meinel.com/branches/bzr/win32/
505
            self.assertNotEqual(builder.cset.entries['2'].contents_change,
506
                                builder.cset.entries['3'].contents_change)
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
507
            cset = builder.merge_changeset(ApplyMerge3)
508
            builder.apply_changeset(cset)
509
            self.assertEqual(builder.this.get_symlink_target("1"), "target2")
510
            self.assertEqual(builder.this.get_symlink_target("2"), "target1")
511
            self.assertEqual(builder.this.get_symlink_target("3"), "target2")
512
            builder.cleanup()
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
513
514
    def test_perms_merge(self):
515
        builder = MergeBuilder()
516
        builder.add_file("1", "0", "name1", "text1", 0755)
1434 by Robert Collins
merge Gustavos executable2 patch
517
        builder.change_perms("1", other=0644)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
518
        builder.add_file("2", "0", "name2", "text2", 0755)
1434 by Robert Collins
merge Gustavos executable2 patch
519
        builder.change_perms("2", base=0644)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
520
        builder.add_file("3", "0", "name3", "text3", 0755)
1434 by Robert Collins
merge Gustavos executable2 patch
521
        builder.change_perms("3", this=0644)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
522
        cset = builder.merge_changeset(ApplyMerge3)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
523
        self.assert_(cset.entries["1"].metadata_change is not None)
524
        self.assert_(isinstance(cset.entries["1"].metadata_change, ExecFlagMerge))
525
        self.assert_(isinstance(cset.entries["2"].metadata_change, ExecFlagMerge))
526
        self.assert_(cset.entries["3"].is_boring())
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
527
        builder.apply_changeset(cset)
1185.38.9 by John Arbash Meinel
[patch] Alexander Belchenko patch #9, skip stat tests for win32
528
        if sys.platform != "win32":
1185.39.1 by Alexey Shamrin
merge forgotten win32 fixes from http://bzr.arbash-meinel.com/branches/bzr/win32/
529
            self.assert_(os.lstat(builder.this.full_path("1")).st_mode &0100 == 0000)
530
            self.assert_(os.lstat(builder.this.full_path("2")).st_mode &0100 == 0100)
531
            self.assert_(os.lstat(builder.this.full_path("3")).st_mode &0100 == 0000)
1092.1.24 by Robert Collins
move merge_core tests into the selftest package. Also reduce double-run of those tests
532
        builder.cleanup();
1092.1.25 by Robert Collins
prepare to write merge tests
533
1448 by Robert Collins
revert symlinks correctly
534
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
535
class FunctionalMergeTest(TestCaseInTempDir):
1092.1.25 by Robert Collins
prepare to write merge tests
536
537
    def test_trivial_star_merge(self):
538
        """Test that merges in a star shape Just Work.""" 
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
539
        from bzrlib.add import smart_add_tree, add_reporter_null
1393.1.5 by Martin Pool
- move copy_branch into bzrlib.clone
540
        from bzrlib.clone import copy_branch
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
541
        from bzrlib.merge import merge
1092.1.33 by Robert Collins
pull the important stuff out of cmd_branch.run to branch.copy_branch
542
        # John starts a branch
1092.1.26 by Robert Collins
start writing star-topology test, realise we need smart-add change
543
        self.build_tree(("original/", "original/file1", "original/file2"))
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
544
        branch = Branch.initialize("original")
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
545
        tree = WorkingTree('original', branch)
546
        smart_add_tree(tree, ["original"], True, add_reporter_null)
547
        tree.commit("start branch.", verbose=False)
1092.1.33 by Robert Collins
pull the important stuff out of cmd_branch.run to branch.copy_branch
548
        # Mary branches it.
1092.1.34 by Robert Collins
unbreak cmd_branch now that something tests the core of it..
549
        self.build_tree(("mary/",))
550
        copy_branch(branch, "mary")
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
551
        # Now John commits a change
552
        file = open("original/file1", "wt")
553
        file.write("John\n")
554
        file.close()
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
555
        branch.working_tree().commit("change file1")
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
556
        # Mary does too
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
557
        mary_branch = Branch.open("mary")
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
558
        file = open("mary/file2", "wt")
559
        file.write("Mary\n")
560
        file.close()
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
561
        mary_branch.working_tree().commit("change file2")
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
562
        # john should be able to merge with no conflicts.
563
        merge_type = ApplyMerge3
1092.1.41 by Robert Collins
merge from abently, take his fixes for merge in preference
564
        base = [None, None]
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
565
        other = ("mary", -1)
1185.12.87 by Aaron Bentley
Updated NEWS, error out if --show-base supplied and unsupported
566
        self.assertRaises(BzrCommandError, merge, other, base, check_clean=True,
567
                          merge_type=WeaveMerge, this_dir="original",
568
                          show_base=True)
569
        merge(other, base, check_clean=True, merge_type=merge_type,
570
              this_dir="original")
1092.1.38 by Robert Collins
make a default merge choose a sane base with branch.common_ancestor
571
        self.assertEqual("John\n", open("original/file1", "rt").read())
572
        self.assertEqual("Mary\n", open("original/file2", "rt").read())
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
573
 
574
    def test_conflicts(self):
575
        os.mkdir('a')
576
        a = Branch.initialize('a')
577
        file('a/file', 'wb').write('contents\n')
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
578
        a.working_tree().add('file')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
579
        a.working_tree().commit('base revision', allow_pointless=False)
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
580
        b = copy_branch(a, 'b')
581
        file('a/file', 'wb').write('other contents\n')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
582
        a.working_tree().commit('other revision', allow_pointless=False)
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
583
        file('b/file', 'wb').write('this contents contents\n')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
584
        b.working_tree().commit('this revision', allow_pointless=False)
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
585
        self.assertEqual(merge(['a', -1], [None, None], this_dir='b'), 1)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
586
        self.assert_(os.path.lexists('b/file.THIS'))
587
        self.assert_(os.path.lexists('b/file.BASE'))
588
        self.assert_(os.path.lexists('b/file.OTHER'))
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
589
        self.assertRaises(WorkingTreeNotRevision, merge, ['a', -1], 
590
                          [None, None], this_dir='b', check_clean=False,
591
                          merge_type=WeaveMerge)
592
        merge(['b', -1], ['b', None], this_dir='b', check_clean=False)
593
        os.unlink('b/file.THIS')
594
        os.unlink('b/file.OTHER')
595
        os.unlink('b/file.BASE')
596
        self.assertEqual(merge(['a', -1], [None, None], this_dir='b', 
597
                               check_clean=False, merge_type=WeaveMerge), 1)
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
598
        self.assert_(os.path.lexists('b/file'))
599
        self.assert_(os.path.lexists('b/file.THIS'))
600
        self.assert_(not os.path.lexists('b/file.BASE'))
601
        self.assert_(os.path.lexists('b/file.OTHER'))
1185.12.85 by Aaron Bentley
Added conflict handling for weave merges
602
1185.12.98 by Aaron Bentley
Support for forcing merges of unrelated trees
603
    def test_merge_unrelated(self):
604
        """Sucessfully merges unrelated branches with no common names"""
605
        os.mkdir('a')
606
        a = Branch.initialize('a')
607
        file('a/a_file', 'wb').write('contents\n')
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
608
        a.working_tree().add('a_file')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
609
        a.working_tree().commit('a_revision', allow_pointless=False)
1185.12.98 by Aaron Bentley
Support for forcing merges of unrelated trees
610
        os.mkdir('b')
611
        b = Branch.initialize('b')
612
        file('b/b_file', 'wb').write('contents\n')
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
613
        b.working_tree().add('b_file')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
614
        b.working_tree().commit('b_revision', allow_pointless=False)
1185.12.98 by Aaron Bentley
Support for forcing merges of unrelated trees
615
        merge(['b', -1], ['b', 0], this_dir='a')
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
616
        self.assert_(os.path.lexists('a/b_file'))
1457.1.14 by Robert Collins
Move pending_merges() to WorkingTree.
617
        self.assertEqual(a.working_tree().pending_merges(),
618
                         [b.last_revision()]) 
1185.12.99 by Aaron Bentley
Handled conflicts with versioned files better
619
620
    def test_merge_unrelated_conflicting(self):
621
        """Sucessfully merges unrelated branches with common names"""
622
        os.mkdir('a')
623
        a = Branch.initialize('a')
624
        file('a/file', 'wb').write('contents\n')
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
625
        a.working_tree().add('file')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
626
        a.working_tree().commit('a_revision', allow_pointless=False)
1185.12.99 by Aaron Bentley
Handled conflicts with versioned files better
627
        os.mkdir('b')
628
        b = Branch.initialize('b')
629
        file('b/file', 'wb').write('contents\n')
1508.1.5 by Robert Collins
Move add from Branch to WorkingTree.
630
        b.working_tree().add('file')
1457.1.17 by Robert Collins
Branch.commit() has moved to WorkingTree.commit(). (Robert Collins)
631
        b.working_tree().commit('b_revision', allow_pointless=False)
1185.12.99 by Aaron Bentley
Handled conflicts with versioned files better
632
        merge(['b', -1], ['b', 0], this_dir='a')
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
633
        self.assert_(os.path.lexists('a/file'))
634
        self.assert_(os.path.lexists('a/file.moved'))
1457.1.14 by Robert Collins
Move pending_merges() to WorkingTree.
635
        self.assertEqual(a.working_tree().pending_merges(), [b.last_revision()])
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
636
637
    def test_merge_metadata_vs_deletion(self):
638
        """Conflict deletion vs metadata change"""
639
        os.mkdir('a')
640
        a = Branch.initialize('a')
641
        file('a/file', 'wb').write('contents\n')
1185.33.27 by Martin Pool
[merge] much integrated work from robert and john
642
        a_wt = a.working_tree()
1508.1.15 by Robert Collins
Merge from mpool.
643
        a_wt.add('file')
1185.33.27 by Martin Pool
[merge] much integrated work from robert and john
644
        a_wt.commit('r0')
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
645
        copy_branch(a, 'b')
646
        b = Branch.open('b')
1185.33.27 by Martin Pool
[merge] much integrated work from robert and john
647
        b_wt = b.working_tree()
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
648
        os.chmod('b/file', 0755)
649
        os.remove('a/file')
1185.33.27 by Martin Pool
[merge] much integrated work from robert and john
650
        a_wt.commit('removed a')
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
651
        self.assertEqual(a.revno(), 2)
652
        self.assertFalse(os.path.exists('a/file'))
1185.33.27 by Martin Pool
[merge] much integrated work from robert and john
653
        b_wt.commit('exec a')
1185.33.23 by Martin Pool
Add test for merging metadata change vs file deletion
654
        merge(['b', -1], ['b', 0], this_dir='a')
655
        self.assert_(os.path.exists('a/file'))