aboutsummaryrefslogtreecommitdiffstats
path: root/dist-tools/git-commit-po-updates.sh
blob: 41b1f65a26619372e43554c941648847b9d96150 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/bin/sh
# dist-tools/git-commit-po-updates.sh
# A helper script to commit translation updates into Git.
# Assumes translation updates are visible to git,
# and one directory above.
#
# © Copyright 2019 - 2020 by Matthias Andree.
# Licensed under the GNU General Public License V2 or,
# at your choice, any later version.
#
# Supported modes:
# -n:   dry-run, only print commands, but do not run them.
# -c:   commit, print commands and run them.

# Exit codes:
# 0: success, no new po/*.po files.
# 1: error
# 2: usage was printed, nothing was done
# 3: new po/*.po files detected
set -eu


cd "$(realpath $(dirname $0))/.."

# see if Perl has Carp::Always available,
# and implicitly fail (set -e) if it hasn't.
perl -MCarp::Always -e ''

usage() {
	printf 'Usage: %s {-n|-c}\n-n: dry-run; -c: commit\n' "$0"
	exit $1
}

# print and potentially run a shell command
run() {
	cmd="$1 '$2'"
	printf '+ %s\n' "$cmd"
	$dryrun_pfx eval "$cmd"
	return $?
}

# try to parse features of a po file and build a git command
handle_po() {
	pofile="$1"
	logmsg1="$2" # "Update", or "Add new"
	logmsg2="$3" # "to", or "for"
	export logmsg1 logmsg2
	if ! cmd="$(perl -WT - "$pofile" <<'_EOF'
use Encode::Locale;
use Encode;
use strict;
use Carp::Always ();
use warnings FATAL => 'uninitialized';
my ($ver, $dat, $translator, $lang, $lcod, $cset, $found);

while(<>)
{
	if (/^"Project-Id-Version: (.+)\\n"/)	{ $ver=$1; };
	if (/^"PO-Revision-Date: (.+)\\n"/)	{ $dat=$1; };
	if (/^"Last-Translator: (.+)\\n"/)	{ $translator=$1; };
	if (/^"Language-Team: ([^<]+?)\s+<.*>\\n"/)
						{ $lang=$1; };
	if (/^"Language: (.+)\\n"/)		{ $lcod=$1; };
	if (/^"Content-Type: text\/plain; charset=(.+)\\n"/)
						{ $cset = $1; };
	if ($ver and $dat and $translator and $lang and $lcod and $cset) {
		$found = 1;
		last;
	}
}

$translator = Encode::decode($cset, $translator);

if ($found) {
	print Encode::encode(locale => "git commit --author '$translator' --date '$dat' -m '$ENV{logmsg1} <$lcod> $lang translation $ENV{logmsg2} $ver'", Encode::FB_CROAK);
} else {
	exit(1);
}
_EOF
)"
	then
		echo >&2 "Parsing $pofile failed, skipping."
		return 23
	fi
	run "$cmd" "$pofile"
	return $?
}

dryrun_pfx=
docommit=
while getopts 'nc' opt ; do
  case $opt in
  n) dryrun_pfx=: ;;
  c) docommit=y ;;
  ?)
     usage 2 ;
  esac
done

rc=0

if [ -z "$dryrun_pfx" -a -z "$docommit" ] ; then usage 2 ; fi

new_po_files=$(git status --porcelain=v1 po/*.po | egrep '^\?|^.\?' | cut -c4-)
printf "%s" "$new_po_files" \
| while read nfile ; do
	run "git add" "$nfile"
	r=$?
	handle_po "$nfile" "Add new" "for"
	if [ $r -ne 0 -o $? -ne 0 ] ; then
		echo "There were errors adding $nfile" >&2 ; rc=1
	fi
done


git diff -G '^"(Project-Id-Version|PO-Revision-Date):' --name-only po/*.po \
| while read pofile ; do
	if ! handle_po "$pofile" "Update" "to" ; then
		echo "There were errors updating $nfile" >&2 ; rc=1
	fi
done

if [ -n "$new_po_files" ] ; then
	printf "Remember to add these codes to po/LINGUAS:"
	for i in $new_po_files ; do
		j=${i%.po}
		j=${j#po/}
		printf " %s" "$j"
	done
	printf '\n'
	rc=3
fi

exit $rc