Here's an updated merge script. I haven't tested my algorithm thoroughly yet, so it probably has bugs.
It can be run as a script that takes 3 files passed to as arguments: the mod file, the vanilla raw file, and the generated raw file. If the generated raw file does not exist, it will create it. It will do a 3 way merge of the mod into the generated_raw file. The script will return 1 if it fails to merge, 0 if it succeeds.
It can also be run with 0 arguements (or any number other than 3), in which case it tests the merger algorithm.
You can also import it as a module and call do_merge_files directly, with the same 3 arguments. do_merge_seq is for comparing lists, which may be useful if you already have the contents of the file as a list of lines.
import difflib, sys, os.path
def do_merge_seq (mod_text, vanilla_text, gen_text):
#if vanilla_text == gen_text: #turn this off for testing
# return (True, mod_text)
van_mod_match = difflib.SequenceMatcher(None, vanilla_text, mod_text)
van_gen_match = difflib.SequenceMatcher(None, vanilla_text, gen_text)
van_mod_ops = van_mod_match.get_opcodes()
van_gen_ops = van_gen_match.get_opcodes()
output_file_temp = []
cur_v = 0
while van_mod_ops and van_gen_ops:
(mod_tag, mod_i1, mod_i2, mod_j1, mod_j2) = van_mod_ops[0]
(gen_tag, gen_i1, gen_i2, gen_j1, gen_j2) = van_gen_ops[0]
#print van_mod_ops[0]
#print van_gen_ops[0]
#print cur_v
if mod_tag == 'equal':
if gen_tag == 'equal' :
if mod_i2 < gen_i2:
output_file_temp += vanilla_text[cur_v:mod_i2]
cur_v = mod_i2
van_mod_ops.pop(0)
else:
output_file_temp += vanilla_text[cur_v:gen_i2]
cur_v = gen_i2
van_gen_ops.pop(0)
if mod_i2 == gen_i2 :
van_mod_ops.pop(0)
else:
output_file_temp += gen_text[gen_j1:gen_j2]
cur_v = gen_i2
van_gen_ops.pop(0)
if mod_i2 == gen_i2 :
van_mod_ops.pop(0)
else:
if gen_tag == 'equal' :
output_file_temp += mod_text[mod_j1:mod_j2]
cur_v = mod_i2
van_mod_ops.pop(0)
if mod_i2 == gen_i2 :
van_gen_ops.pop(0)
else:
return (False, "")
#print (output_file_temp)
if van_mod_ops:
(mod_tag, mod_i1, mod_i2, mod_j1, mod_j2) = van_mod_ops[0]
output_file_temp += mod_text[mod_j1:mod_j2]
if van_gen_ops:
(gen_tag, gen_i1, gen_i2, gen_j1, gen_j2) = van_gen_ops[0]
output_file_temp += gen_text[gen_j1:gen_j2]
return (True, output_file_temp)
def do_merge_files(mod_file_name,van_file_name,gen_file_name):
van_file = open(van_file_name)
if os.path.isfile(gen_file_name):
gen_file = open(gen_file_name,"r")
gen_lines = gen_file.readlines()
else:
gen_lines = []
mod_file = open(mod_file_name)
(can_merge, output_file) = do_merge_seq (mod_file.readlines(), \
van_file.readlines(), gen_lines)
sys.stderr.write(str(can_merge))
if can_merge:
if(gen_lines):
gen_file.close()
gen_file = open(gen_file_name,"w")
gen_file.write("".join(gen_lines))
return False
else:
return True
def test_merge(vanilla_file, test_mods):
output_file = vanilla_file
print ("----")
print output_file
for mod in test_mods:
print " + " + mod
(can_merge, output_file) = do_merge_seq (mod, vanilla_file, output_file)
if can_merge:
print ''.join(output_file)
else:
print "CANNOT MERGE"
break;
if __name__ == "__main__":
print ("====")
if len(sys.argv) == 4:
mod_file_name = sys.argv[1]
van_file_name = sys.argv[2]
gen_file_name = sys.argv[3]
exit(int(do_merge_files(mod_file_name,van_file_name,gen_file_name)))
else:
test_merge("vanilla",['anything at all'])
test_merge("vanilla",['oooh'])
test_merge("vanilla",['nilla', 'vanill'])
test_merge("vanilla",['vonilla', 'banana'])
test_merge("vanilla",['banana', 'vonilla'])
test_merge("vanilla",['banana', 'vanilla'])
test_merge("vanilla",['vanilla', 'banana'])
test_merge ('vanilla',['vonilla','vnilla'])
test_merge ('vanilla',['van','la'])
test_merge ('vanilla',['vani','lla'])
test_merge ('vanilla',['vonilla','venilla'])
test_merge ('vanilla',['nilla','lla'])
test_merge ('vanilla',['vanilla and more','vanilla and more'])
test_merge ('vanilla',['more and vanilla','more and vanilla'])