def main(repo): if repo.index.conflicts: print("You need to resolve merge conflicts first.") return 1 try: repo.lookup_reference('MERGE_HEAD') print("Not running mapmerge for merge commit.") return 0 except KeyError: pass changed = 0 for path, status in repo.status().items(): if path.endswith(".dmm") and ( status & (pygit2.GIT_STATUS_INDEX_MODIFIED | pygit2.GIT_STATUS_INDEX_NEW)): # read the index index_entry = repo.index[path] index_map = dmm.DMM.from_bytes(repo[index_entry.id].read_raw()) try: head_blob = repo[repo[repo.head.target].tree[path].id] except KeyError: # New map, no entry in HEAD print(f"Converting new map: {path}", flush=True) assert (status & pygit2.GIT_STATUS_INDEX_NEW) merged_map = index_map else: # Entry in HEAD, merge the index over it print(f"Merging map: {path}", flush=True) assert not (status & pygit2.GIT_STATUS_INDEX_NEW) head_map = dmm.DMM.from_bytes(head_blob.read_raw()) merged_map = merge_map(index_map, head_map) # write to the index blob_id = repo.create_blob(merged_map.to_bytes()) repo.index.add(pygit2.IndexEntry(path, blob_id, index_entry.mode)) changed += 1 # write to the working directory if that's clean if status & (pygit2.GIT_STATUS_WT_DELETED | pygit2.GIT_STATUS_WT_MODIFIED): print( f"Warning: {path} has unindexed changes, not overwriting them" ) else: merged_map.to_file(os.path.join(repo.workdir, path)) if changed: repo.index.write() print(f"Merged {changed} maps.") return 0
def main(repo): if repo.index.conflicts: print("You need to resolve merge conflicts first.") return 1 try: repo.lookup_reference('MERGE_HEAD') print("Not running mapmerge for merge commit.") return 0 except KeyError: pass changed = 0 for path, status in repo.status().items(): if path.endswith(".dmm") and (status & (pygit2.GIT_STATUS_INDEX_MODIFIED | pygit2.GIT_STATUS_INDEX_NEW)): # read the index index_entry = repo.index[path] index_map = dmm.DMM.from_bytes(repo[index_entry.id].read_raw()) try: head_blob = repo[repo[repo.head.target].tree[path].id] except KeyError: # New map, no entry in HEAD print(f"Converting new map: {path}") assert (status & pygit2.GIT_STATUS_INDEX_NEW) merged_map = index_map else: # Entry in HEAD, merge the index over it print(f"Merging map: {path}") assert not (status & pygit2.GIT_STATUS_INDEX_NEW) head_map = dmm.DMM.from_bytes(head_blob.read_raw()) merged_map = merge_map(index_map, head_map) # write to the index blob_id = repo.create_blob(merged_map.to_bytes()) repo.index.add(pygit2.IndexEntry(path, blob_id, index_entry.mode)) changed += 1 # write to the working directory if that's clean if status & (pygit2.GIT_STATUS_WT_DELETED | pygit2.GIT_STATUS_WT_MODIFIED): print(f"Warning: {path} has unindexed changes, not overwriting them") else: merged_map.to_file(os.path.join(repo.workdir, path)) if changed: repo.index.write() print(f"Merged {changed} maps.") return 0
def three_way_merge(base, left, right): if base.size != left.size or base.size != right.size: print("Dimensions have changed:") print(f" Base: {base.size}") print(f" Ours: {left.size}") print(f" Theirs: {right.size}") return True, None trouble = False merged = dmm.DMM(base.key_length, base.size) merged.dictionary = base.dictionary.copy() for (z, y, x) in base.coords_zyx: coord = x, y, z base_tile = base.get_tile(coord) left_tile = left.get_tile(coord) right_tile = right.get_tile(coord) # try to merge the whole tiles whole_tile_merge = select(base_tile, left_tile, right_tile, debug='tile') if whole_tile_merge is not None: merged.set_tile(coord, whole_tile_merge) continue # try to merge each group independently (movables, turfs, areas) base_movables, base_turfs, base_areas = dmm.split_atom_groups( base_tile) left_movables, left_turfs, left_areas = dmm.split_atom_groups( left_tile) right_movables, right_turfs, right_areas = dmm.split_atom_groups( right_tile) merged_movables = select(base_movables, left_movables, right_movables, debug='movable') merged_turfs = select(base_turfs, left_turfs, right_turfs, debug='turf') merged_areas = select(base_areas, left_areas, right_areas, debug='area') if merged_movables is not None and merged_turfs is not None and merged_areas is not None: merged.set_tile(coord, merged_movables + merged_turfs + merged_areas) continue # TODO: more advanced strategies? # fall back to requiring manual conflict resolution trouble = True print(f" C: Both sides touch the tile at {coord}") if merged_movables is None: merged_movables = left_movables + ['/obj'] + right_movables print( f" Left and right movable groups are split by a generic `/obj`" ) if merged_turfs is None: merged_turfs = left_turfs print(f" Saving turf: {', '.join(left_turfs)}") print(f" Alternative: {', '.join(right_turfs)}") print(f" Original: {', '.join(base_turfs)}") if merged_areas is None: merged_areas = left_areas print(f" Saving area: {', '.join(left_areas)}") print(f" Alternative: {', '.join(right_areas)}") print(f" Original: {', '.join(base_areas)}") merged.set_tile(coord, merged_movables + merged_turfs + merged_areas) merged = mapmerge.merge_map(merged, base) return trouble, merged