3 # Three-way merge driver for PO files
9 local parent_lineno="$1"
12 if [[ -n "$message" ]] ; then
13 echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
15 echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
19 # trap 'on_error ${LINENO}' ERR
21 # given a file, find the path that matches its contents
23 hash=`git hash-object "${1}"`
24 git ls-tree -r HEAD | fgrep "$hash" | cut -b54-
27 # wraps msgmerge with default options
29 msgmerge --force-po --quiet --no-fuzzy-matching $@
32 # wraps msgcat with default options
38 # removes the "graveyard strings" from the input
43 # removes the "graveyard strings" from the input
48 # select messages with a conflict marker
49 # pass -v to inverse selection
51 msggrep $@ --msgstr -F -e '#-#-#' -
54 # select messages from $1 that are also in $2 but whose contents have changed
58 | m_msgmerge -o - $1 - \
67 TEMP=`mktemp /tmp/merge-po.XXXX`
69 echo "Using custom PO merge driver (`show_file ${LOCAL}`; $TEMP)"
71 # Extract the PO header from the current branch (top of file until first empty line)
72 sed -e '/^$/q' < $LOCAL > ${TEMP}.header
75 msguniq --force-po -o ${TEMP}.base --unique ${BASE}
76 msguniq --force-po -o ${TEMP}.local --unique ${LOCAL}
77 msguniq --force-po -o ${TEMP}.remote --unique ${REMOTE}
79 # messages changed on local
80 extract_changes ${TEMP}.local ${TEMP}.base > ${TEMP}.local-changes
82 # messages changed on remote
83 extract_changes ${TEMP}.remote ${TEMP}.base > ${TEMP}.remote-changes
86 m_msgcat -o - ${TEMP}.base ${TEMP}.local ${TEMP}.remote \
90 # messages changed on both local and remote (conflicts)
91 m_msgcat -o - ${TEMP}.remote-changes ${TEMP}.local-changes \
95 # messages changed on local, not on remote; and vice-versa
96 m_msgcat -o ${TEMP}.local-only --unique ${TEMP}.local-changes ${TEMP}.conflicts
97 m_msgcat -o ${TEMP}.remote-only --unique ${TEMP}.remote-changes ${TEMP}.conflicts
100 m_msgcat -o ${TEMP}.merge1 ${TEMP}.unchanged ${TEMP}.conflicts ${TEMP}.local-only ${TEMP}.remote-only
102 # create a template to filter messages actually needed (those on local and remote)
103 m_msgcat -o - ${TEMP}.local ${TEMP}.remote \
104 | m_msgmerge -o ${TEMP}.merge2 ${TEMP}.merge1 -
106 # final merge, adds saved header
107 m_msgcat -o ${TEMP}.merge3 --use-first ${TEMP}.header ${TEMP}.merge2
109 # produce output file (overwrites input LOCAL file)
110 cat ${TEMP}.merge3 | replace_graveyard > $OUTPUT
112 # check for conflicts
113 if grep '#-#' $OUTPUT > /dev/null ; then
114 echo "Conflict(s) detected"
115 echo " between ${TEMP}.local and ${TEMP}.remote"