Skip to content

Instantly share code, notes, and snippets.

@davehampson
Created January 5, 2015 09:37
Show Gist options
  • Save davehampson/6806b7d64adedb1dafa6 to your computer and use it in GitHub Desktop.
Save davehampson/6806b7d64adedb1dafa6 to your computer and use it in GitHub Desktop.
import csv, os, subprocess
def Main():
unityPid = GetUnityProcessID()
if unityPid:
print('Error: Unity is running (process ID {})'.format(unityPid))
return 1
# Make sure we have all heads that we need to merge locally:
RunCommand(['hg', 'pull', '-b', '.'])
# Check if the working directory is clean:
revision = GetOutput(['hg', 'id', '-i']).rstrip()
if revision.endswith('+'):
print('Error: Working directory is not clean, please commit your changes before merging')
return 1
# First use mercurial's merging:
RunCommand(['hg', 'merge', '--tool', 'internal:merge'], showOutput = False)
# Then get a list of files which remain to resolve:
output = GetOutput(['hg', 'resolve', '-l'])
resolveList = output.splitlines()
for entry in resolveList:
type = entry[0]
pathname = entry[2:]
if type == 'U':
ResolveFile(pathname)
RunCommand(['hg', 'commit', '-m', 'Scripted merge of Unity project'])
return 0
def ResolveFile(pathname):
name = os.path.split(pathname)[1]
lower = pathname.lower()
outputs = ('_data/managed/assembly-csharp.dll',
'_data/maindata',
'_data/output_log.txt',
'_data/resources.assets',
'_data/sharedassets0.assets')
takeLocal = False
if lower.endswith(outputs):
takeLocal = True
if takeLocal:
ResolveLocal(pathname)
if lower.endswith('.unity'):
ResolveYAML(pathname)
def ResolveLocal(pathname):
RunCommand(['hg', 'resolve', '--tool', 'internal:local', pathname])
os.remove(pathname + '.orig')
def ResolveYAML(pathname):
# First get access to the base, other and local YAML files:
RunCommand(['hg', 'resolve', '--tool', 'internal:dump', pathname])
# UnityYAMLMerge doesn't like merging files if they don't have the extension '.unity' so we need to rename them:
baseName = pathname + '.base'
otherName = pathname + '.other'
localName = pathname + '.local'
baseUnity = baseName + '.unity'
otherUnity = otherName + '.unity'
localUnity = localName + '.unity'
os.rename(baseName, baseUnity)
os.rename(otherName, otherUnity)
os.rename(localName, localUnity)
# Run the semantic merge:
scriptDir = os.path.dirname(os.path.realpath(__file__))
yamlMerge = os.path.join(scriptDir, 'UnityYAMLMerge.exe')
RunCommand([yamlMerge, 'merge', '-r', baseUnity, otherUnity, localUnity, pathname])
# Mark the output file as resolved:
RunCommand(['hg', 'resolve', '-m', pathname])
# Delete the temporary files:
os.remove(baseUnity)
os.remove(otherUnity)
os.remove(localUnity)
os.remove(pathname + '.orig')
# Wrapper to run a command using subprocess:
def RunCommand(args, showOutput = True):
print(subprocess.list2cmdline(args))
if showOutput:
process = subprocess.Popen(args)
else:
process = subprocess.Popen(args, stdout = open(os.devnull, 'w'), stderr=subprocess.STDOUT)
retcode = process.wait()
return retcode
# Run a command using subprocess and get the output
def GetOutput(args):
stdout, stderr = subprocess.Popen(args, stdout = subprocess.PIPE).communicate()
return stdout
def GetUnityProcessID():
output = GetOutput(['tasklist.exe', '/fo', 'csv', '/nh'])
lines = output.splitlines()
for line in csv.reader(lines):
if line[0].lower() == 'unity.exe':
return line[1]
return None
if __name__ == '__main__':
exit(Main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment