Last active
November 8, 2021 09:08
-
-
Save oadam/a02f862ac7a88579ea2743986c9be121 to your computer and use it in GitHub Desktop.
Gettext po file git merge driver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.po merge=pofile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[merge "pofile"] | |
name = custom merge driver for gettext po files | |
driver = po-merge-driver.py %A %O %B |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import importlib | |
import subprocess | |
import sys | |
def default_merge_and_exit(): | |
print(f"running default git merge", file=sys.stderr) | |
subprocess.run(['git', 'merge-file', '-L', 'ours', '-L', 'base', '-L', 'theirs', sys.argv[1], sys.argv[2], sys.argv[3]]) | |
exit(1) | |
# check if polib is available | |
try: | |
import polib | |
except ModuleNotFoundError as err: | |
print('polib is not installed', file=sys.stderr) | |
default_merge_and_exit() | |
try: | |
# create 3 dictionnaries | |
ours={} | |
for e in polib.pofile(sys.argv[1]): | |
ours[e.msgid]=e.msgstr | |
base={} | |
for e in polib.pofile(sys.argv[2]): | |
base[e.msgid]=e.msgstr | |
theirs={} | |
for e in polib.pofile(sys.argv[3]): | |
theirs[e.msgid]=e.msgstr | |
all_keys=set(ours.keys()) | |
all_keys.update(base.keys()) | |
all_keys.update(theirs.keys()) | |
# check for conflicts | |
conflicts=[] | |
for key in sorted(all_keys): | |
presence = (key in ours, key in base, key in theirs) | |
if presence == (False, True, True) and base[key] != theirs[key]: | |
conflicts.append(f"key removed by us and modified by them : {key}") | |
if presence == (True, True, False) and base[key] != ours[key]: | |
conflicts.append(f"key removed by them and modified by us : {key}") | |
if presence == (True, False, True) and ours[key] != theirs[key]: | |
conflicts.append(f"key added by them and us in a different way : {key}") | |
if presence == (True, True, True) and base[key] != ours[key] and base[key] != theirs[key] and ours[key] != theirs[key]: | |
conflicts.append(f"key modified by them and us in a different way : {key}") | |
if conflicts: | |
print(f"\nERROR : automerge for {sys.argv[1]} will conflict :", file=sys.stderr) | |
for c in conflicts: | |
print(c, file=sys.stderr) | |
print("\n", file=sys.stderr) | |
default_merge_and_exit() | |
# update ours_po, knowing that there are no conflicts | |
ours_po=polib.pofile(sys.argv[1]) | |
# mutate all entries with their modifications | |
for e in ours_po: | |
key=e.msgid | |
if key in theirs and key in base and theirs[key] != base[key]: | |
e.msgstr = theirs[key] | |
# remove all entries removed by them | |
# mutate the object without creating a new one https://stackoverflow.com/a/1208792/436792 | |
ours_po[:] = [e for e in ours_po if e.msgid in theirs] | |
# add all entries introduced by them | |
theirs_po=polib.pofile(sys.argv[3]) | |
for e in theirs_po: | |
key=e.msgid | |
if key not in ours: | |
ours_po.append(e) | |
# save result | |
ours_po.save(sys.argv[1]) | |
# format result | |
formatted = subprocess.check_output(['msgcat', '--sort-output',sys.argv[1]], text=True) | |
open(sys.argv[1], 'w').write(formatted) | |
except BaseException: | |
default_merge_and_exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment