~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge_core.py

  • Committer: Martin Pool
  • Date: 2005-07-07 08:02:16 UTC
  • Revision ID: mbp@sourcefrog.net-20050707080216-4e4d884bcf89eb8d
- Merge merge updates from aaron

  aaron.bentley@utoronto.ca-20050706170931-9d2551019af3578d

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
    for entry in cset.entries.itervalues():
49
49
        if entry.is_boring():
50
50
            new_cset.add_entry(entry)
51
 
        elif entry.is_creation(False):
52
 
            if inventory.this.get_path(entry.id) is None:
53
 
                new_cset.add_entry(entry)
54
 
            else:
55
 
                this_contents = get_this_contents(entry.id)
56
 
                other_contents = entry.contents_change.new_contents
57
 
                if other_contents == this_contents:
58
 
                    boring_entry = changeset.ChangesetEntry(entry.id, 
59
 
                                                            entry.new_parent, 
60
 
                                                            entry.new_path)
61
 
                    new_cset.add_entry(boring_entry)
62
 
                else:
63
 
                    conflict_handler.contents_conflict(this_contents, 
64
 
                                                       other_contents)
65
 
 
66
 
        elif entry.is_deletion(False):
67
 
            if inventory.this.get_path(entry.id) is None:
68
 
                boring_entry = changeset.ChangesetEntry(entry.id, entry.parent, 
69
 
                                                        entry.path)
70
 
                new_cset.add_entry(boring_entry)
71
 
            elif entry.contents_change is not None:
72
 
                this_contents = get_this_contents(entry.id) 
73
 
                base_contents = entry.contents_change.old_contents
74
 
                if base_contents == this_contents:
75
 
                    new_cset.add_entry(entry)
76
 
                else:
77
 
                    entry_path = inventory.this.get_path(entry.id)
78
 
                    conflict_handler.rem_contents_conflict(entry_path,
79
 
                                                           this_contents, 
80
 
                                                           base_contents)
81
 
 
82
 
            else:
83
 
                new_cset.add_entry(entry)
84
51
        else:
85
 
            entry = get_merge_entry(entry, inventory, base, other, 
86
 
                                    conflict_handler)
87
 
            if entry is not None:
88
 
                new_cset.add_entry(entry)
 
52
            new_entry = make_merged_entry(entry, inventory, conflict_handler)
 
53
            new_contents = make_merged_contents(entry, this, base, other,
 
54
                                                conflict_handler)
 
55
            new_entry.contents_change = new_contents
 
56
            new_entry.metadata_change = make_merged_metadata(entry, base, other)
 
57
            new_cset.add_entry(new_entry)
 
58
 
89
59
    return new_cset
90
60
 
91
 
 
92
 
def get_merge_entry(entry, inventory, base, other, conflict_handler):
 
61
def make_merged_entry(entry, inventory, conflict_handler):
93
62
    this_name = inventory.this.get_name(entry.id)
94
63
    this_parent = inventory.this.get_parent(entry.id)
95
64
    this_dir = inventory.this.get_dir(entry.id)
96
65
    if this_dir is None:
97
66
        this_dir = ""
98
 
    if this_name is None:
99
 
        return conflict_handler.merge_missing(entry.id, inventory)
100
67
 
101
68
    base_name = inventory.base.get_name(entry.id)
102
69
    base_parent = inventory.base.get_parent(entry.id)
133
100
            old_dir = this_dir
134
101
            new_parent = other_parent
135
102
            new_dir = other_dir
136
 
    old_path = os.path.join(old_dir, old_name)
 
103
    if old_name is not None and old_parent is not None:
 
104
        old_path = os.path.join(old_dir, old_name)
 
105
    else:
 
106
        old_path = None
137
107
    new_entry = changeset.ChangesetEntry(entry.id, old_parent, old_name)
138
 
    if new_name is not None or new_parent is not None:
 
108
    if new_name is not None and new_parent is not None:
139
109
        new_entry.new_path = os.path.join(new_dir, new_name)
140
110
    else:
141
111
        new_entry.new_path = None
142
112
    new_entry.new_parent = new_parent
143
 
 
144
 
    base_path = base.readonly_path(entry.id)
145
 
    other_path = other.readonly_path(entry.id)
 
113
    return new_entry
 
114
 
 
115
 
 
116
def make_merged_contents(entry, this, base, other, conflict_handler):
 
117
    contents = entry.contents_change
 
118
    if contents is None:
 
119
        return None
 
120
    this_path = this.readonly_path(entry.id)
 
121
    def make_diff3():
 
122
        if this_path is None:
 
123
            return conflict_handler.missing_for_merge(entry.id, inventory)
 
124
        base_path = base.readonly_path(entry.id)
 
125
        other_path = other.readonly_path(entry.id)    
 
126
        return changeset.Diff3Merge(base_path, other_path)
 
127
 
 
128
    if isinstance(contents, changeset.PatchApply):
 
129
        return make_diff3()
 
130
    if isinstance(contents, changeset.ReplaceContents):
 
131
        if contents.old_contents is None and contents.new_contents is None:
 
132
            return None
 
133
        if contents.new_contents is None:
 
134
            if this_path is not None and os.path.exists(this_path):
 
135
                return contents
 
136
            else:
 
137
                return None
 
138
        elif contents.old_contents is None:
 
139
            if this_path is None or not os.path.exists(this_path):
 
140
                return contents
 
141
            else:
 
142
                this_contents = file(this_path, "rb").read()
 
143
                if this_contents == contents.new_contents:
 
144
                    return None
 
145
                else:
 
146
                    other_path = other.readonly_path(entry.id)    
 
147
                    conflict_handler.new_contents_conflict(this_path, 
 
148
                                                           other_path)
 
149
        elif isinstance(contents.old_contents, changeset.FileCreate) and \
 
150
            isinstance(contents.new_contents, changeset.FileCreate):
 
151
            return make_diff3()
 
152
        else:
 
153
            raise Exception("Unhandled merge scenario")
 
154
 
 
155
def make_merged_metadata(entry, base, other):
 
156
    if entry.metadata_change is not None:
 
157
        base_path = base.readonly_path(entry.id)
 
158
        other_path = other.readonly_path(entry.id)    
 
159
        return PermissionsMerge(base_path, other_path)
146
160
    
 
161
def get_merge_entry(entry, inventory, base, other, conflict_handler):
147
162
    if entry.contents_change is not None:
148
163
        new_entry.contents_change = changeset.Diff3Merge(base_path, other_path)
149
164
    if entry.metadata_change is not None:
210
225
    def full_path(self, id):
211
226
        return self.abs_path(self.inventory[id])
212
227
 
 
228
    def readonly_path(self, id):
 
229
        return self.full_path(id)
 
230
 
213
231
    def change_path(self, id, path):
214
232
        new = os.path.join(self.dir, self.inventory[id])
215
233
        os.rename(self.abs_path(self.inventory[id]), self.abs_path(path))
329
347
                                          Inventory(self.base.inventory), 
330
348
                                          Inventory(self.other.inventory))
331
349
        conflict_handler = changeset.ExceptionConflictHandler(self.this.dir)
332
 
        return make_merge_changeset(self.cset, all_inventory, self.this.dir,
333
 
                                    self.base.dir, self.other.dir, 
334
 
                                    conflict_handler)
 
350
        return make_merge_changeset(self.cset, all_inventory, self.this,
 
351
                                    self.base, self.other, conflict_handler)
 
352
 
 
353
    def apply_inv_change(self, inventory_change, orig_inventory):
 
354
        orig_inventory_by_path = {}
 
355
        for file_id, path in orig_inventory.iteritems():
 
356
            orig_inventory_by_path[path] = file_id
 
357
 
 
358
        def parent_id(file_id):
 
359
            try:
 
360
                parent_dir = os.path.dirname(orig_inventory[file_id])
 
361
            except:
 
362
                print file_id
 
363
                raise
 
364
            if parent_dir == "":
 
365
                return None
 
366
            return orig_inventory_by_path[parent_dir]
 
367
        
 
368
        def new_path(file_id):
 
369
            if inventory_change.has_key(file_id):
 
370
                return inventory_change[file_id]
 
371
            else:
 
372
                parent = parent_id(file_id)
 
373
                if parent is None:
 
374
                    return orig_inventory[file_id]
 
375
                dirname = new_path(parent)
 
376
                return os.path.join(dirname, orig_inventory[file_id])
 
377
 
 
378
        new_inventory = {}
 
379
        for file_id in orig_inventory.iterkeys():
 
380
            path = new_path(file_id)
 
381
            if path is None:
 
382
                continue
 
383
            new_inventory[file_id] = path
 
384
 
 
385
        for file_id, path in inventory_change.iteritems():
 
386
            if orig_inventory.has_key(file_id):
 
387
                continue
 
388
            new_inventory[file_id] = path
 
389
        return new_inventory
 
390
 
 
391
        
 
392
 
335
393
    def apply_changeset(self, cset, conflict_handler=None, reverse=False):
336
 
        self.this.inventory = \
337
 
            changeset.apply_changeset(cset, self.this.inventory,
338
 
                                      self.this.dir, conflict_handler,
339
 
                                      reverse)
 
394
        inventory_change = changeset.apply_changeset(cset,
 
395
                                                     self.this.inventory,
 
396
                                                     self.this.dir,
 
397
                                                     conflict_handler, reverse)
 
398
        self.this.inventory =  self.apply_inv_change(inventory_change, 
 
399
                                                     self.this.inventory)
 
400
 
 
401
                    
 
402
        
 
403
 
340
404
        
341
405
    def cleanup(self):
342
406
        shutil.rmtree(self.dir)