mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-05-19 05:09:49 +01:00
9f124e5b14
* Initial * Remove corrupt dmis * Fixup maps in TGM format4e5a32721f: maps/_templates_and_guidance/Public Event Templates/Maze_Reward_-_Copy.dmm4e5a32721f: maps/_templates_and_guidance/Templates/shelter_Medical.dmm4e5a32721f: maps/expedition_vr/aerostat/aerostat.dmm4e5a32721f: maps/expedition_vr/aerostat/aerostat_science_outpost.dmm4e5a32721f: maps/expedition_vr/beach/submaps/deadBeacon.dmm4e5a32721f: maps/expedition_vr/wild/tether_wild-crash-alt.dmm4e5a32721f: maps/expedition_vr/wild/tether_wild-crash.dmm4e5a32721f: maps/expedition_vr/wild/tether_wild-surface.dmm4e5a32721f: maps/expedition_vr/wild/tether_wild-temple.dmm4e5a32721f: maps/gateway_vr/lucky_7.dmm4e5a32721f: maps/gateway_vr/snow_outpost.dmm4e5a32721f: maps/overmap/_map.dmm4e5a32721f: maps/overmap/bearcat/bearcat.dmm4e5a32721f: maps/overmap/example_sector1.dmm4e5a32721f: maps/overmap/example_sector2.dmm4e5a32721f: maps/redgate/falls/falls.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/CaveS.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/DeadSettlers1.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/DeadSettlers2.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/DoomP.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/Lab1.dmm4e5a32721f: maps/submaps/pois_vr/aerostat/Rockybase.dmm4e5a32721f: maps/submaps/pois_vr/debris_field/debris14.dmm4e5a32721f: maps/submaps/pois_vr/debris_field/derelict.dmm4e5a32721f: maps/submaps/pois_vr/debris_field/new_escapepod_xeno.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/BlastMine1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/CaveTrench.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Cavelake.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Cliff1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/CrashedMedShuttle1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Geyser1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Geyser2.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Geyser3.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Mineshaft1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/Scave1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/SupplyDrop1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crashed_ufo.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crashed_ufo_frigate.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crashedcontainmentshuttle.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crystal1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crystal2.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/crystal3.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/deadBeacon.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/deadly_rabbit_vr.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/deadspy.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/digsite.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/excavation1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/lava_trench.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/prepper1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/ritual.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/spatial_anomaly.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/speakeasy_vr.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault1.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault2.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault3.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault4.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault5.dmm4e5a32721f: maps/submaps/surface_submaps/mountains/vault6.dmm4e5a32721f: maps/submaps/surface_submaps/plains/Boathouse.dmm4e5a32721f: maps/submaps/surface_submaps/plains/BuriedTreasure.dmm4e5a32721f: maps/submaps/surface_submaps/plains/BuriedTreasure2.dmm4e5a32721f: maps/submaps/surface_submaps/plains/BuriedTreasure3.dmm4e5a32721f: maps/submaps/surface_submaps/plains/Oldhouse.dmm4e5a32721f: maps/submaps/surface_submaps/plains/PooledR.dmm4e5a32721f: maps/submaps/surface_submaps/plains/Rocky5.dmm4e5a32721f: maps/submaps/surface_submaps/plains/Shakden.dmm4e5a32721f: maps/submaps/surface_submaps/plains/Thiefc.dmm4e5a32721f: maps/submaps/surface_submaps/plains/beacons.dmm4e5a32721f: maps/submaps/surface_submaps/plains/chemspill1.dmm4e5a32721f: maps/submaps/surface_submaps/plains/farm1.dmm4e5a32721f: maps/submaps/surface_submaps/plains/house1.dmm4e5a32721f: maps/submaps/surface_submaps/plains/lonehome.dmm4e5a32721f: maps/submaps/surface_submaps/plains/smol2.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Blackshuttledown.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Blueshuttledown.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Boombase.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/CaveS.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Chapel.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Cragzone1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DJOutpost1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DJOutpost2.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DJOutpost3.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DJOutpost4.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DecoupledEngine.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/DoomP.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Drugden.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Epod3.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Epod4.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Flake.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/FrostflyNest.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/MCamp1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/MHR.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Manor1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Mudpit.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Rocky1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Rocky3.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Rocky4.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Rockybase.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Shack1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Shelter.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Smol1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/Snowrock1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/borglab.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/butchershack.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/chasm.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/chemspill2.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/deathden.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/derelictengine.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/frostoasis.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/kururakden.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/spider1.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/wolfden.dmm4e5a32721f: maps/submaps/surface_submaps/wilderness/xenohive.dmm4e5a32721f: maps/tether/tether-02-surface2.dmm4e5a32721f: maps/virgo_minitest/virgo_minitest-sector-2.dmm Automatically commited by: tools\mapmerge2\fixup.py * Remove unnecessary whitespace edits from mapmerger * Cable dirs update path * Fix area var edits * Put the area over there * Ignore archive maps folder * Forgot to port multivar support too * A few changes I forgot about for hook install * restore multivar support that chomp doesn't have yet * ban those * Forgot to add code for the marker too * Couple more of these invalid cables were added in master * Update multiple_blood_effects.yml * Update multiple_blood_effects.yml * Fixup maps in TGM format612ca9cbb9: maps/tether/submaps/tether_misc.dmm Automatically commited by: tools\mapmerge2\fixup.py * Fixup now logs the map its currently checking * Final fixes? * Fixup maps in TGM format3078e5cd0a: maps/expedition_vr/beach/submaps/crashedcontainmentshuttle.dmm3078e5cd0a: maps/redgate/fantasy_dungeon.dmm3078e5cd0a: maps/submaps/pois_vr/aerostat/Rockybase.dmm3078e5cd0a: maps/submaps/surface_submaps/mountains/crashedcontainmentshuttle_vr.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/Oldhouse_vr.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/dogbase.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/greatwolfden.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/lonehome_vr.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/methlab.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/oldhotel.dmm3078e5cd0a: maps/submaps/surface_submaps/plains/priderock.dmm3078e5cd0a: maps/submaps/surface_submaps/wilderness/Rockybase.dmm3078e5cd0a: maps/submaps/surface_submaps/wilderness/demonpool.dmm3078e5cd0a: maps/submaps/surface_submaps/wilderness/dogbase.dmm3078e5cd0a: maps/submaps/surface_submaps/wilderness/greatwolfden.dmm3078e5cd0a: maps/tether/submaps/underdark_pois/abandonded_outpost.dmm3078e5cd0a: maps/tether/submaps/underdark_pois/phoron_rat_den.dmm Automatically commited by: tools\mapmerge2\fixup.py * Fix tether_misc error * Remap reused solar farm area * Fix erroneous bearcat entries * Fix weird whitespace (most archive maps also affected but didn't bother) * misc mdb cleanup * moar * grr --------- Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
170 lines
5.8 KiB
Python
170 lines
5.8 KiB
Python
# merge_frontend.py
|
|
import sys
|
|
import io
|
|
import os
|
|
import pygit2
|
|
import collections
|
|
import typing
|
|
|
|
|
|
ENCODING = 'utf-8'
|
|
|
|
|
|
class MergeReturn(typing.NamedTuple):
|
|
success: bool
|
|
merge_result: typing.Optional[object]
|
|
|
|
|
|
class MergeDriver:
|
|
driver_id: typing.Optional[str] = None
|
|
|
|
def pre_announce(self, path: str):
|
|
"""
|
|
Called before merge() is called, with a human-friendly path for output.
|
|
"""
|
|
print(f"Merging {self.driver_id}: {path}")
|
|
|
|
def merge(self, base: typing.BinaryIO, left: typing.BinaryIO, right: typing.BinaryIO) -> MergeReturn:
|
|
"""
|
|
Read from three BinaryIOs: base (common ancestor), left (ours), and
|
|
right (theirs). Perform the actual three-way merge operation. Leave
|
|
conflict markers if necessary.
|
|
|
|
Return (False, None) to indicate the merge driver totally failed.
|
|
Return (False, merge_result) if the result contains conflict markers.
|
|
Return (True, merge_result) if everything went smoothly.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
def to_file(self, output: typing.BinaryIO, merge_result: object):
|
|
"""
|
|
Save the merge() result to the given output stream.
|
|
Override this if the merge() result is not bytes or str.
|
|
"""
|
|
if isinstance(merge_result, bytes):
|
|
output.write(merge_result)
|
|
elif isinstance(merge_result, str):
|
|
with io.TextIOWrapper(output, ENCODING) as f:
|
|
f.write(merge_result)
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
def post_announce(self, success: bool, merge_result: object):
|
|
"""
|
|
Called after merge() is called, to warn the user if action is needed.
|
|
"""
|
|
if not success:
|
|
print("!!! Manual merge required")
|
|
if merge_result:
|
|
print(" A best-effort merge was performed. You must finish the job yourself.")
|
|
else:
|
|
print(" No merge was possible. You must resolve the conflict yourself.")
|
|
|
|
def main(self, args: typing.List[str] = None):
|
|
return _main(self, args or sys.argv[1:])
|
|
|
|
|
|
def _main(driver: MergeDriver, args: typing.List[str]):
|
|
if len(args) > 0 and args[0] == '--posthoc':
|
|
return _posthoc_main(driver, args[1:])
|
|
else:
|
|
return _driver_main(driver, args)
|
|
|
|
|
|
def _driver_main(driver: MergeDriver, args: typing.List[str]):
|
|
"""
|
|
Act like a normal Git merge driver, called by Git during a merge.
|
|
"""
|
|
if len(args) != 5:
|
|
print("merge driver called with wrong number of arguments")
|
|
print(" usage: %P %O %A %B %L")
|
|
return 1
|
|
|
|
path, path_base, path_left, path_right, _ = args
|
|
driver.pre_announce(path)
|
|
|
|
with open(path_base, 'rb') as io_base:
|
|
with open(path_left, 'rb') as io_left:
|
|
with open(path_right, 'rb') as io_right:
|
|
success, merge_result = driver.merge(io_base, io_left, io_right)
|
|
|
|
if merge_result:
|
|
# If we got anything, write it to the working directory.
|
|
with open(path_left, 'wb') as io_output:
|
|
driver.to_file(io_output, merge_result)
|
|
|
|
driver.post_announce(success, merge_result)
|
|
if not success:
|
|
# If we were not successful, do not mark the conflict as resolved.
|
|
return 1
|
|
|
|
|
|
def _posthoc_main(driver: MergeDriver, args: typing.List[str]):
|
|
"""
|
|
Apply merge driver logic to a repository which is already in a conflicted
|
|
state, running the driver on any conflicted files.
|
|
"""
|
|
repo_dir = pygit2.discover_repository(os.getcwd())
|
|
repo = pygit2.Repository(repo_dir)
|
|
conflicts = repo.index.conflicts
|
|
if not conflicts:
|
|
print("There are no unresolved conflicts.")
|
|
return 0
|
|
|
|
all_success = True
|
|
index_changed = False
|
|
any_attempted = False
|
|
for base, left, right in list(conflicts):
|
|
if not base or not left or not right:
|
|
# (not left) or (not right): deleted in one branch, modified in the other.
|
|
# (not base): added differently in both branches.
|
|
# In either case, there's nothing we can do for now.
|
|
continue
|
|
|
|
path = left.path
|
|
if not _applies_to(repo, driver, path):
|
|
# Skip the file if it's not the right extension.
|
|
continue
|
|
|
|
any_attempted = True
|
|
driver.pre_announce(path)
|
|
io_base = io.BytesIO(repo[base.id].data)
|
|
io_left = io.BytesIO(repo[left.id].data)
|
|
io_right = io.BytesIO(repo[right.id].data)
|
|
success, merge_result = driver.merge(io_base, io_left, io_right)
|
|
if merge_result:
|
|
# If we got anything, write it to the working directory.
|
|
with open(os.path.join(repo.workdir, path), 'wb') as io_output:
|
|
driver.to_file(io_output, merge_result)
|
|
|
|
if success:
|
|
# If we were successful, mark the conflict as resolved.
|
|
with open(os.path.join(repo.workdir, path), 'rb') as io_readback:
|
|
contents = io_readback.read()
|
|
merged_id = repo.create_blob(contents)
|
|
repo.index.add(pygit2.IndexEntry(path, merged_id, left.mode))
|
|
del conflicts[path]
|
|
index_changed = True
|
|
if not success:
|
|
all_success = False
|
|
driver.post_announce(success, merge_result)
|
|
|
|
if index_changed:
|
|
repo.index.write()
|
|
|
|
if not any_attempted:
|
|
print("There are no unresolved", driver.driver_id, "conflicts.")
|
|
|
|
if not all_success:
|
|
# Not usually observed, but indicate the failure just in case.
|
|
return 1
|
|
|
|
|
|
def _applies_to(repo: pygit2.Repository, driver: MergeDriver, path: str):
|
|
"""
|
|
Check if the current merge driver is a candidate to handle a given path.
|
|
"""
|
|
if not driver.driver_id:
|
|
raise ValueError('Driver must have ID to perform post-hoc merge')
|
|
return repo.get_attr(path, 'merge') == driver.driver_id
|