~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge_core.py

  • Committer: Aaron Bentley
  • Date: 2005-08-10 21:43:27 UTC
  • mto: (1092.1.41) (1185.3.4) (974.1.47)
  • mto: This revision was merged to the branch mainline in revision 1110.
  • Revision ID: abentley@panoramicfeedback.com-20050810214327-4e8c22e4cba24527
Eliminated ThreeWayInventory

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
        self.contents_change.apply(filename, conflict_handler, reverse)
70
70
 
71
71
 
72
 
class ThreewayInventory(object):
73
 
    def __init__(self, this_inventory, base_inventory, other_inventory):
74
 
        self.this = this_inventory
75
 
        self.base = base_inventory
76
 
        self.other = other_inventory
77
72
def invert_invent(inventory):
78
73
    invert_invent = {}
79
74
    for file_id in inventory:
85
80
        invert_invent[file_id] = path
86
81
    return invert_invent
87
82
 
88
 
def make_inv(inventory):
89
 
    return Inventory(invert_invent(inventory))
90
 
        
91
83
 
92
84
def merge_flex(this, base, other, changeset_function, inventory_function,
93
85
               conflict_handler, merge_factory, interesting_ids):
94
 
    this_inventory = inventory_function(this)
95
 
    base_inventory = inventory_function(base)
96
 
    other_inventory = inventory_function(other)
97
 
    inventory = ThreewayInventory(make_inv(this_inventory),
98
 
                                  make_inv(base_inventory), 
99
 
                                  make_inv(other_inventory))
100
86
    cset = changeset_function(base, other, interesting_ids)
101
 
    new_cset = make_merge_changeset(cset, inventory, this, base, other, 
 
87
    new_cset = make_merge_changeset(cset, this, base, other, 
102
88
                                    conflict_handler, merge_factory)
103
 
    result = apply_changeset(new_cset, invert_invent(this_inventory),
 
89
    result = apply_changeset(new_cset, invert_invent(this.tree.inventory),
104
90
                             this.root, conflict_handler, False)
105
91
    conflict_handler.finalize()
106
92
    return result
107
93
 
108
94
    
109
95
 
110
 
def make_merge_changeset(cset, inventory, this, base, other, 
 
96
def make_merge_changeset(cset, this, base, other, 
111
97
                         conflict_handler, merge_factory):
112
98
    new_cset = changeset.Changeset()
113
99
    def get_this_contents(id):
114
 
        path = os.path.join(this.root, inventory.this.get_path(id))
 
100
        path = this.readonly_path(id)
115
101
        if os.path.isdir(path):
116
102
            return changeset.dir_create
117
103
        else:
121
107
        if entry.is_boring():
122
108
            new_cset.add_entry(entry)
123
109
        else:
124
 
            new_entry = make_merged_entry(entry, inventory, conflict_handler)
 
110
            new_entry = make_merged_entry(entry, this, base, other, 
 
111
                                          conflict_handler)
125
112
            new_contents = make_merged_contents(entry, this, base, other, 
126
 
                                                inventory, conflict_handler, 
 
113
                                                conflict_handler,
127
114
                                                merge_factory)
128
115
            new_entry.contents_change = new_contents
129
116
            new_entry.metadata_change = make_merged_metadata(entry, base, other)
131
118
 
132
119
    return new_cset
133
120
 
134
 
def make_merged_entry(entry, inventory, conflict_handler):
 
121
def make_merged_entry(entry, this, base, other, conflict_handler):
135
122
    from bzrlib.trace import mutter
136
 
    this_name = inventory.this.get_name(entry.id)
137
 
    this_parent = inventory.this.get_parent(entry.id)
138
 
    this_dir = inventory.this.get_dir(entry.id)
139
 
    if this_dir is None:
140
 
        this_dir = ""
141
 
 
142
 
    base_name = inventory.base.get_name(entry.id)
143
 
    base_parent = inventory.base.get_parent(entry.id)
144
 
    base_dir = inventory.base.get_dir(entry.id)
145
 
    if base_dir is None:
146
 
        base_dir = ""
147
 
    other_name = inventory.other.get_name(entry.id)
148
 
    other_parent = inventory.other.get_parent(entry.id)
149
 
    other_dir = inventory.base.get_dir(entry.id)
150
 
    if other_dir is None:
151
 
        other_dir = ""
 
123
    def entry_data(file_id, tree):
 
124
        assert hasattr(tree, "__contains__"), "%s" % tree
 
125
        if file_id not in tree:
 
126
            return (None, None, "")
 
127
        entry = tree.tree.inventory[file_id]
 
128
        my_dir = tree.id2path(entry.parent_id)
 
129
        if my_dir is None:
 
130
            my_dir = ""
 
131
        return entry.name, entry.parent_id, my_dir 
 
132
    this_name, this_parent, this_dir = entry_data(entry.id, this)
 
133
    base_name, base_parent, base_dir = entry_data(entry.id, base)
 
134
    other_name, other_parent, other_dir = entry_data(entry.id, other)
152
135
    mutter("Dirs: this, base, other %r %r %r" % (this_dir, base_dir, other_dir))
153
136
    mutter("Names: this, base, other %r %r %r" % (this_name, base_name, other_name))
154
137
    if base_name == other_name:
169
152
        new_dir = this_dir
170
153
    else:
171
154
        if this_parent != base_parent and this_parent != other_parent:
172
 
            conflict_handler.move_conflict(entry.id, inventory)
 
155
            conflict_handler.move_conflict(entry.id, this_dir, base_dir, 
 
156
                                           other_dir)
173
157
        else:
174
158
            old_parent = this_parent
175
159
            old_dir = this_dir
189
173
    return new_entry
190
174
 
191
175
 
192
 
def make_merged_contents(entry, this, base, other, inventory, conflict_handler,
 
176
def make_merged_contents(entry, this, base, other, conflict_handler,
193
177
                         merge_factory):
194
178
    contents = entry.contents_change
195
179
    if contents is None:
197
181
    this_path = this.readonly_path(entry.id)
198
182
    def make_merge():
199
183
        if this_path is None:
200
 
            return conflict_handler.missing_for_merge(entry.id, inventory)
 
184
            return conflict_handler.missing_for_merge(entry.id, 
 
185
                                                      other.id2path(entry.id))
201
186
        base_path = base.readonly_path(entry.id)
202
187
        other_path = other.readonly_path(entry.id)    
203
188
        return merge_factory(base_path, other_path)
262
247
import unittest
263
248
import tempfile
264
249
import shutil
 
250
from bzrlib.inventory import InventoryEntry, RootEntry
 
251
from osutils import file_kind
 
252
class FalseTree(object):
 
253
    def __init__(self, realtree):
 
254
        self._realtree = realtree
 
255
        self.inventory = self
 
256
 
 
257
    def __getitem__(self, file_id):
 
258
        entry = self.make_inventory_entry(file_id)
 
259
        if entry is None:
 
260
            raise KeyError(file_id)
 
261
        return entry
 
262
        
 
263
    def make_inventory_entry(self, file_id):
 
264
        path = self._realtree.inventory.get(file_id)
 
265
        if path is None:
 
266
            return None
 
267
        if path == "":
 
268
            return RootEntry(file_id)
 
269
        dir, name = os.path.split(path)
 
270
        kind = file_kind(self._realtree.abs_path(path))
 
271
        for parent_id, path in self._realtree.inventory.iteritems():
 
272
            if path == dir:
 
273
                break
 
274
        if path != dir:
 
275
            raise Exception("Can't find parent for %s" % name)
 
276
        return InventoryEntry(file_id, name, kind, parent_id)
 
277
 
 
278
 
265
279
class MergeTree(object):
266
280
    def __init__(self, dir):
267
281
        self.dir = dir;
268
282
        os.mkdir(dir)
269
283
        self.inventory = {'0': ""}
 
284
        self.tree = FalseTree(self)
270
285
    
271
286
    def child_path(self, parent, name):
272
287
        return os.path.join(self.inventory[parent], name)
304
319
    def readonly_path(self, id):
305
320
        return self.full_path(id)
306
321
 
 
322
    def __contains__(self, file_id):
 
323
        return file_id in self.inventory
 
324
 
 
325
    def id2path(self, file_id):
 
326
        return self.inventory[file_id]
 
327
 
307
328
    def change_path(self, id, path):
308
329
        new = os.path.join(self.dir, self.inventory[id])
309
330
        os.rename(self.abs_path(self.inventory[id]), self.abs_path(path))
435
456
        os.chmod(tree.full_path(id), mode)
436
457
 
437
458
    def merge_changeset(self, merge_factory):
438
 
        all_inventory = ThreewayInventory(Inventory(self.this.inventory),
439
 
                                          Inventory(self.base.inventory), 
440
 
                                          Inventory(self.other.inventory))
441
459
        conflict_handler = changeset.ExceptionConflictHandler(self.this.dir)
442
 
        return make_merge_changeset(self.cset, all_inventory, self.this,
443
 
                                    self.base, self.other, conflict_handler,
 
460
        return make_merge_changeset(self.cset, self.this, self.base,
 
461
                                    self.other, conflict_handler,
444
462
                                    merge_factory)
445
463
 
446
464
    def apply_inv_change(self, inventory_change, orig_inventory):