{"thread":{"id":"29870","subject":"[PATCH] Maintaince script for l10n files and commits","startedAt":"2012-03-07T18:47:14Z","lastAt":"2012-03-10T09:17:29Z","messageCount":10,"participants":["Jiang Xin","Junio C Hamano","David Aguilar"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"186327","messageId":"1331146034-85804-1-git-send-email-worldhello.net@gmail.com","threadId":"29870","inReplyTo":null,"subject":"[PATCH] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-07T18:47:14Z","receivedAt":"2012-03-07T18:47:14Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Usage of this script:\n\n * rake commits      : Check commit logs written with non-ascii chars,\n                       but without the correct encoding settings.\n                       Always report Non-ascii in subject line as error.\n\n * rake pot          : Print the summary of the update of git.pot file\n\n * rake XX.po        : Create or update XX.po from the git.po tempolate file\n\n * rake check[XX.po] : Syntax check on XX.po\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n po/Rakefile |  157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 157 insertions(+)\n create mode 100644 po/Rakefile\n\ndiff --git a/po/Rakefile b/po/Rakefile\nnew file mode 100644\nindex 00000..e581b\n--- /dev/null\n+++ b/po/Rakefile\n@@ -0,0 +1,157 @@\n+require 'tempfile'\n+\n+POTFILE=\"git.pot\"\n+\n+class NonAsciiInSubjectError < Exception\n+end\n+\n+class BadEncodingError < Exception\n+end\n+\n+def shellout(cmd)\n+    pipe = IO.popen(cmd)\n+    pipe.readlines\n+end\n+\n+desc \"Syntax check on XX.po, or all .po files if nothing provided.\"\n+task :check, :po_file do |t, args|\n+    if args[:po_file]\n+        if File.exists? args[:po_file]\n+            system(\"msgfmt -o /dev/null --check --statistics #{args[:po_file]}\")\n+        else\n+            $stderr.puts \"File #{args[:po_file]} does not exist.\"\n+        end\n+    else\n+        FileList[\"*.po\"].each do |po_file|\n+            puts \"=\" * 72\n+            puts \"Check #{po_file}...\"\n+            system(\"msgfmt -o /dev/null --check --statistics #{po_file}\")\n+        end\n+    end\n+end\n+\n+desc \"Show summary of updates of git.pot\"\n+task :pot do\n+    status = shellout(\"git status --porcelain -- #{POTFILE}\")\n+    new = []\n+    dropped = []\n+    tmpfile = Tempfile.new('git.pot')\n+    if status.empty?\n+        puts \"Nothing changed.\"\n+    else\n+        ENV[\"LANGUAGE\"] = \"C\"\n+        system(\"git show HEAD:./git.pot > #{tmpfile.path}\")\n+        msgcmp = shellout(\"msgcmp -N --use-untranslated #{tmpfile.path} #{POTFILE} 2>&1\")\n+        msgcmp.each do |line|\n+            if m = /^.*:([0-9]+): this message is used but not defined in/.match(line)\n+                new << m[1]\n+            elsif m = /^.*:([0-9]+): warning: this message is not used/.match(line)\n+                dropped << m[1]\n+            end\n+        end\n+        puts \"Update of #{POTFILE}:\"\n+        puts\n+        if not new.empty?\n+            puts \" * Add #{new.count} new l10n string#{new.count>1 ? \"s\":\"\"}\" +\n+                 \" in the new generated \\\"git.pot\\\" file at\" +\n+                 \" line#{new.count>1? \"s\":\"\"}:\"\n+            puts \"   \" + new.join(\", \")\n+            puts\n+        end\n+        if not dropped.empty?\n+            puts \" * Remove #{dropped.count} l10n string#{dropped.count>1 ?\n+                 \"s\":\"\"} from the old \\\"git.pot\\\" file at line\" +\n+                 \"#{dropped.count>1 ? \"s\":\"\"}:\"\n+            puts \"   \" + dropped.join(\", \")\n+        end\n+    end\n+end\n+\n+# raise Exception if commit has bad encoding setting\n+def verify_commit_encoding(commit, log)\n+    subject = 0\n+    non_ascii = nil\n+    encoding = nil\n+    log.each do |line|\n+        if line.chomp!.empty?\n+            # next line would be the commit log subject line,\n+            # if no previous empty line found.\n+            subject += 1\n+            next\n+        end\n+        if subject == 0 and line =~ /^encoding /\n+            encoding = line.chomp.sub(/^encoding /, '')\n+        end\n+        # non-ascii found in commit log\n+        if match = /([^[:alnum:][:punct:][:space:]]+)/.match(line)\n+            non_ascii = \"#{line} << #{match[1][0..9]}\"\n+            # subject must be written in english\n+            raise NonAsciiInSubjectError.new(non_ascii) if subject == 1\n+        end\n+        # subject has only one line\n+        subject += 1 if subject == 1\n+        # break if there are non-asciis and has already checked subject line\n+        break if non_ascii && subject > 0\n+    end\n+\n+    return if not non_ascii\n+\n+    encoding = 'UTF-8' if not encoding\n+    cmd = \"python -c \\\"s='''#{\n+              log.collect!{\n+                |x| x.chomp.gsub(/['\"]/, \"\")\n+              }.join(' - ')}'''; s.decode('#{encoding}')\\\" 2>/dev/null\"\n+    raise BadEncodingError.new(non_ascii) if not system(cmd)\n+end\n+\n+desc \"Check commits for bad encoding settings.\"\n+task :commits, :from, :to do |t, args|\n+    from = args[:from] || 'origin/master'\n+    to = args[:to] || 'HEAD'\n+    commits = shellout(\"git rev-list #{from}..#{to}\")\n+    commits.each do |c|\n+        c.chomp!\n+        log = shellout(\"git cat-file commit #{c}\")\n+        begin\n+            verify_commit_encoding(c, log)\n+        rescue BadEncodingError => e\n+            $stderr.puts \"=\" * 78\n+            $stderr.puts \"Error: Bad encoding setting found in commit #{c[0,7]}:\"\n+            $stderr.puts \"       >> #{e.message}\"\n+            $stderr.puts\n+            log.each {|line| puts \"\\t\" + line.chomp}\n+        rescue NonAsciiInSubjectError => e\n+            $stderr.puts \"=\" * 78\n+            $stderr.puts \"Error: Non-AscII found in subject in commit #{c[0,7]}:\"\n+            $stderr.puts \"       >> #{e.message}\"\n+            $stderr.puts\n+            log.each {|line| puts \"\\t\" + line.chomp}\n+        end\n+    end\n+end\n+\n+\n+desc \"Create or update XX.po file from git.pot\"\n+task \"XX.po\" do\n+    $stderr.puts \"Use your real locale file, such as zh_CN.po\"\n+end\n+\n+# Update XX.po even if timestamp of XX.po is newer\n+FileList[\"*.po\"].each do |t|\n+    task t => POTFILE\n+end\n+\n+rule '.po' => POTFILE do |t|\n+    if File.exist?(t.name)\n+        system(\"msgmerge --add-location --backup=off -U #{t.name} #{t.source}\")\n+    else\n+        system(\"msginit -i #{t.source} --locale=#{t.name.sub(/.po$/, '')}\")\n+    end\n+    mofile=\"build/locale/#{t.name.sub(/.po$/, '')}/LC_MESSAGES/git.mo\"\n+    FileUtils.mkdir_p File.dirname(mofile)\n+    system(\"msgfmt -o #{mofile} --check --statistics #{t.name}\")\n+end\n+\n+task :default do\n+    system(\"rake -T\")\n+end\n-- \n1.7.9.2.330.gaa956.dirty\n"},{"id":"186330","messageId":"7vr4x4mdae.fsf@alter.siamese.dyndns.org","threadId":"29870","inReplyTo":"1331146034-85804-1-git-send-email-worldhello.net@gmail.com","subject":"Re: [PATCH] Maintaince script for l10n files and commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-03-07T19:17:13Z","receivedAt":"2012-03-07T19:17:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> Usage of this script:\n>\n>  * rake commits      : Check commit logs written with non-ascii chars,\n>                        but without the correct encoding settings.\n>                        Always report Non-ascii in subject line as error.\n>\n>  * rake pot          : Print the summary of the update of git.pot file\n>\n>  * rake XX.po        : Create or update XX.po from the git.po tempolate file\n>\n>  * rake check[XX.po] : Syntax check on XX.po\n\nI would relly prefer not to add another language dependency to the\nsystem.  Are you doing anything that cannot be done with what we\nalready use, e.g. make and shell?\n"},{"id":"186460","messageId":"1331222706-81728-1-git-send-email-worldhello.net@gmail.com","threadId":"29870","inReplyTo":"7vr4x4mdae.fsf@alter.siamese.dyndns.org","subject":"[PATCH] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-08T16:05:06Z","receivedAt":"2012-03-08T16:05:06Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Usage of this script:\n\n * po-helper.sh XX.po   : Init or update XX.po from git.pot\n\n * po-helper.sh check [XX.po]\n                        : Perform all the checks for XX.po\n\n * po-helper.sh commits [since] [til]\n                        : Check non-ascii chars in commit logs\n\n                          Don't write commit log with non-ascii chars\n                          without proper encoding settings.\n\n                          Subject of commit log must written in English.\n\n                          Don't change files outside this directory (po/)\n\n * po-helper.sh pot     : Display summary of updates of git.pot file\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n po/po-helper.sh |  271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 271 insertions(+)\n create mode 100755 po/po-helper.sh\n\ndiff --git a/po/po-helper.sh b/po/po-helper.sh\nnew file mode 100755\nindex 0000000..dd370a5\n--- /dev/null\n+++ b/po/po-helper.sh\n@@ -0,0 +1,271 @@\n+#!/bin/bash\n+#\n+# Copyright (c) 2012 Jiang Xin\n+\n+POTFILE=git.pot\n+\n+usage()\n+{\n+    cat <<-END_OF_USAGE\n+Maintaince script for l10n files and commits.\n+\n+Usage:\n+\n+ * po-helper.sh XX.po   : Init or update XX.po from git.pot\n+\n+ * po-helper.sh check [XX.po]\n+                        : Perform all the checks for XX.po\n+\n+ * po-helper.sh commits [since] [til]\n+                        : Check non-ascii chars in commit logs\n+\n+                          Don't write commit log with non-ascii chars\n+                          without proper encoding settings.\n+\n+                          Subject of commit log must written in English.\n+\n+                          Don't change files outside this directory (po/)\n+\n+ * po-helper.sh pot     : Display summary of updates of git.pot file\n+\n+END_OF_USAGE\n+\n+    exit 1\n+}\n+\n+# Display summary of updates of git.pot\n+show_pot_update_summary()\n+{\n+    pnew=\"^.*:([0-9]+): this message is used but not defined in\"\n+    pdel=\"^.*:([0-9]+): warning: this message is not used\"\n+    new_count=0\n+    del_count=0\n+    new_lineno=\"\"\n+    del_lineno=\"\"\n+\n+    status=$(git status --porcelain -- $POTFILE)\n+    if [ -z \"$status\" ]; then\n+        echo \"Nothing changed.\"\n+    else\n+        tmpfile=$(mktemp /tmp/git.po.XXXX)\n+        LANGUAGE=C git show HEAD:./git.pot > $tmpfile\n+        LANGUAGE=C msgcmp -N --use-untranslated $tmpfile $POTFILE 2>&1 |\n+        {    while read line; do\n+                if [[ $line =~ $pnew ]]; then\n+                    new_count=$(( new_count + 1 ))\n+                    if [ -z \"$new_lineno\" ]; then\n+                        new_lineno=\"${BASH_REMATCH[1]}\"\n+                    else\n+                        new_lineno=\"${new_lineno}, ${BASH_REMATCH[1]}\"\n+                    fi\n+                fi\n+                if [[ $line =~ $pdel ]]; then\n+                    del_count=$(( del_count + 1 ))\n+                    if [ -z \"$del_lineno\" ]; then\n+                        del_lineno=\"${BASH_REMATCH[1]}\"\n+                    else\n+                        del_lineno=\"${del_lineno}, ${BASH_REMATCH[1]}\"\n+                    fi\n+                fi\n+            done\n+            [ $new_count -gt 1 ] && new_plur=\"s\" || new_plur=\"\"\n+            [ $del_count -gt 1 ] && del_plur=\"s\" || del_plur=\"\"\n+            echo \"Updates of $POTFILE since last update:\"\n+            echo\n+            echo \" * Add ${new_count} new l10n message${new_plur}\" \\\n+                 \"in the new generated \\\"git.pot\\\" file at\" \\\n+                 \"line${new_plur}:\"\n+            echo \"   ${new_lineno}\"\n+            echo\n+\n+            echo \" * Remove ${del_count} l10n message${del_plur}\" \\\n+                 \"from the old \\\"git.pot\\\" file at line${del_plur}:\"\n+            echo \"   ${del_lineno}\"\n+        }\n+        rm $tmpfile\n+    fi\n+}\n+\n+# Syntax check on XX.po, or all .po files if nothing provided\n+check_po()\n+{\n+    if [ $# -eq 0 ]; then\n+        ls *.po | while read f; do\n+            echo \"============================================================\"\n+            echo \"Check $f...\"\n+            check_po $f\n+        done\n+    fi\n+    while [ $# -gt 0 ]; do\n+        po=$1\n+        shift\n+        if [ -f $po ]; then\n+            msgfmt -o /dev/null --check --statistics $po\n+        else\n+            echo \"Error: File $po does not exist.\" >&2\n+        fi\n+    done\n+}\n+\n+# Create or update XX.po file from git.pot\n+create_or_update_po()\n+{\n+    if [ $# -eq 0 ]; then\n+        usage\n+    fi\n+    while [ $# -gt 0 ]; do\n+        po=$1\n+        shift\n+        if [ -f $po ]; then\n+            msgmerge --add-location --backup=off -U $po $POTFILE\n+        else\n+            msginit -i $POTFILE --locale=${po%.po}\n+            perl -pi -e 's/(?<=\"Project-Id-Version: )PACKAGE VERSION/Git/' $po\n+        fi\n+        mo=\"build/locale/${po%.po}/LC_MESSAGES/git.mo\"\n+        mkdir -p $(dirname $mo)\n+        msgfmt -o $mo --check --statistics $po\n+    done\n+}\n+\n+\n+verify_commit_encoding()\n+{\n+    c=$1\n+    subject=0\n+    non_ascii=\"\"\n+    encoding=\"\"\n+    log=\"\"\n+\n+    git cat-file commit $c |\n+    {\n+        while read line; do\n+            log=\"$log - $line\"\n+            # next line would be the commit log subject line,\n+            # if no previous empty line found.\n+            if [ -z \"$line\" ]; then\n+                subject=$((subject + 1))\n+                continue\n+            fi\n+            pencoding=\"^encoding (.+)\"\n+            if [ $subject -eq 0 ] && [[ $line =~ $pencoding ]]; then\n+                encoding=\"${BASH_REMATCH[1]}\"\n+            fi\n+            # non-ascii found in commit log\n+            pnonascii=\"([^[:alnum:][:space:][:punct:]]+)\"\n+            if [[ $line =~ $pnonascii ]]; then\n+                non_ascii=\"${BASH_REMATCH[1]} >> $line <<\"\n+                if [ $subject -eq 1 ]; then\n+                    report_nonascii_in_subject $c \"$non_ascii\"\n+                    return\n+                fi\n+            fi\n+            # subject has only one line\n+            [ $subject -eq 1 ] && subject=$((subject += 1))\n+            # break if there are non-asciis and has already checked subject line\n+            if [ -n \"$non_ascii\" ] && [ $subject -gt 0 ]; then\n+                break\n+            fi\n+        done\n+        if [ -n \"$non_ascii\" ]; then\n+            if [ -z \"$encoding\" ]; then\n+                echo $line | iconv -f UTF-8 -t UTF-8 -s >/dev/null ||\n+                report_bad_encoding \"$c\" \"$non_ascii\"\n+            else\n+                echo $line | iconv -f $encoding -t UTF-8 -s >/dev/null ||\n+                report_bad_encoding \"$c\" \"$non_ascii\" \"$encoding\"\n+            fi\n+        fi\n+    }\n+}\n+\n+report_nonascii_in_subject()\n+{\n+    c=$1\n+    non_ascii=$2\n+\n+    echo \"============================================================\" >&2\n+    echo \"Error: Non-ASCII in subject of commit $c:\"                    >&2\n+    echo \"       ${non_ascii}\"                                          >&2\n+    echo\n+    git cat-file commit $c | head -15 | while read line; do\n+        echo \"\\t$line\"                                                  >&2\n+    done\n+}\n+\n+report_bad_encoding()\n+{\n+    c=$1\n+    non_ascii=$2\n+    encoding=$3\n+\n+    echo \"============================================================\" >&2\n+    if [ -z \"$encoding\" ]; then\n+        echo \"Error: Not have encoding setting for commit $c:\"          >&2\n+    else\n+        echo \"Error: Wrong encoding ($encoding) for commit $c:\"         >&2\n+    fi\n+    echo \"       ${non_ascii}\"                                          >&2\n+    echo                                                                >&2\n+    git cat-file commit $c | head -15 | while read line; do\n+        echo \"\\t$line\"                                                  >&2\n+    done\n+}\n+\n+# Check commit logs for bad encoding settings\n+check_commits()\n+{\n+    if [ $# -gt 2 ]; then\n+        usage\n+    fi\n+    since=${1:-origin/master}\n+    til=${2:-HEAD}\n+\n+    git diff-tree -r $since $til | awk '{print $6}' |\n+    while read f; do\n+        if [[ ! $f =~ ^po/ ]]; then\n+            echo \"Error: changed files ($f...) outside po directory!\"   >&2\n+            echo \"       reference: git diff-tree -r $since $til\"       >&2\n+        fi\n+    done\n+\n+    count=0\n+    git rev-list ${since}..${til} |\n+    {   while read c; do\n+            verify_commit_encoding $c\n+            count=$(( count + 1 ))\n+        done\n+        echo\n+        echo \"$count commits check complete.\"\n+    }\n+}\n+\n+\n+[ $# -eq 0 ] && usage\n+\n+while [ $# -ne 0 ]; do\n+    case \"$1\" in\n+    pot|git.pot)\n+        show_pot_update_summary\n+        ;;\n+    *.po)\n+        create_or_update_po $1\n+        ;;\n+    check)\n+        shift\n+        check_po $*\n+        exit 0\n+        ;;\n+    commit|commits)\n+        shift\n+        check_commits $*\n+        exit 0\n+        ;;\n+    *)\n+        usage\n+        ;;\n+    esac\n+    shift\n+done\n+\n+# vim: et ts=4 sw=4\n-- \n1.7.9.2.330.gaa956.dirty\n"},{"id":"186492","messageId":"7v399iddw3.fsf@alter.siamese.dyndns.org","threadId":"29870","inReplyTo":"1331222706-81728-1-git-send-email-worldhello.net@gmail.com","subject":"Re: [PATCH] Maintaince script for l10n files and commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-03-08T20:41:16Z","receivedAt":"2012-03-08T20:41:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> Usage of this script:\n>\n>  * po-helper.sh XX.po   : Init or update XX.po from git.pot\n>\n>  * po-helper.sh check [XX.po]\n>                         : Perform all the checks for XX.po\n>\n>  * po-helper.sh commits [since] [til]\n>                         : Check non-ascii chars in commit logs\n>\n>                           Don't write commit log with non-ascii chars\n>                           without proper encoding settings.\n>\n>                           Subject of commit log must written in English.\n>\n>                           Don't change files outside this directory (po/)\n>\n>  * po-helper.sh pot     : Display summary of updates of git.pot file\n\nThat's quite a style deviation from out norm in the commit log\nmessages, don't you think (see \"git log --no-merges -100\", for\nexample)?  State the problem you are attempting to solve first, and\nexplain the solution to the problem, in separate paragraphs for\nreadability, perhaps like this:\n\n\tThere are routine tasks translators need to perform that can\n\tbe automated.\n\n\tHelp them to\n\n         (1) initialize or update the message files;\n         (2) check errors in the message files they edited;\n         (3) check errors in their commits; and\n         (4) review recent updates to the message template file\n             they base their translations on.\n\n        by adding a helper script.\n\n> Signed-off-by: Jiang Xin <worldhello.net@gmail.com>\n> ---\n>  po/po-helper.sh |  271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 271 insertions(+)\n>  create mode 100755 po/po-helper.sh\n>\n> diff --git a/po/po-helper.sh b/po/po-helper.sh\n> new file mode 100755\n> index 0000000..dd370a5\n> --- /dev/null\n> +++ b/po/po-helper.sh\n> @@ -0,0 +1,271 @@\n> +#!/bin/bash\n\nIs there any bash-ism in this script?  Otherwise please start this\nwith \"#!/bin/sh\" to allow people who do not use bash to get involved\nin the project.\n\n> +#\n> +# Copyright (c) 2012 Jiang Xin\n> +\n> +POTFILE=git.pot\n> +\n> +usage()\n> +{\n\nStyle:\n\n\tusage () {\n\nIn general, it is safe to mimic the style \"git-am.sh\" is written in,\nalthough some crufts seem to have slipped in with recent updates.\n\n> +    cat <<-END_OF_USAGE\n\nStyle: unless you have substitutions ($var etc.) inside the here\ntext, please quote the end token to make it clear that readers do\nnot have to scan and look for what is substituted, i.e.\n\n\tcat <<-\\END_OF_USAGE\n\n> +Maintaince script for l10n files and commits.\n> +\n> +Usage:\n> +\n> + * po-helper.sh XX.po   : Init or update XX.po from git.pot\n\nWill we later regret that we didn't give a command word for this\none?  Two common sources of such risks are:\n\n (1) it turns out XX.po matches the pattern we would want to use as\n     a command; and\n\n (2) it turns out \"init/update\" is not the most often used action.\n\nI do not think (1) is likely. I do not think anybody can decide\nabout (2) at this point yet.\n\n> + * po-helper.sh check [XX.po]\n> +                        : Perform all the checks for XX.po\n> +\n> + * po-helper.sh commits [since] [til]\n> +                        : Check non-ascii chars in commit logs\n> +\n> +                          Don't write commit log with non-ascii chars\n> +                          without proper encoding settings.\n> +\n> +                          Subject of commit log must written in English.\n> +\n> +                          Don't change files outside this directory (po/)\n> +\n> + * po-helper.sh pot     : Display summary of updates of git.pot file\n> +\n> +END_OF_USAGE\n\nDo you really want the blank line output at the end?\n\n> +\n> +    exit 1\n> +}\n> +\n> +# Display summary of updates of git.pot\n> +show_pot_update_summary()\n> +{\n> +    pnew=\"^.*:([0-9]+): this message is used but not defined in\"\n> +    pdel=\"^.*:([0-9]+): warning: this message is not used\"\n> +    new_count=0\n> +    del_count=0\n> +    new_lineno=\"\"\n> +    del_lineno=\"\"\n> +\n> +    status=$(git status --porcelain -- $POTFILE)\n> +    if [ -z \"$status\" ]; then\n> +        echo \"Nothing changed.\"\n> +    else\n> +        tmpfile=$(mktemp /tmp/git.po.XXXX)\n> +        LANGUAGE=C git show HEAD:./git.pot > $tmpfile\n> +        LANGUAGE=C msgcmp -N --use-untranslated $tmpfile $POTFILE 2>&1 |\n> +        {    while read line; do\n> +                if [[ $line =~ $pnew ]]; then\n\nThat sounds like a blatant bash-ism to me.\n\n> +...\n> +}\n> +\n> +# Syntax check on XX.po, or all .po files if nothing provided\n> +check_po()\n> +{\n> +    if [ $# -eq 0 ]; then\n> +        ls *.po | while read f; do\n> +            echo \"============================================================\"\n\nStyle:\n\n\tif test $# = 0\n        then\n\t\tls *.po |\n\t\twhile read f\n\t\tdo\n                \t...\n\nAlso indentation is done with HT, not runs of SP.\n\n> +# Create or update XX.po file from git.pot\n> +create_or_update_po()\n> +{\n> +    if [ $# -eq 0 ]; then\n> +        usage\n> +    fi\n> +    while [ $# -gt 0 ]; do\n> +        po=$1\n> +        shift\n> +        if [ -f $po ]; then\n> +            msgmerge --add-location --backup=off -U $po $POTFILE\n> +        else\n> +            msginit -i $POTFILE --locale=${po%.po}\n> +            perl -pi -e 's/(?<=\"Project-Id-Version: )PACKAGE VERSION/Git/' $po\n\nAh ;-) show_pot_update_summary() can be written so that this script\ndoes not have to rely on bash-ism at all, as you are going to use\nPerl anyway.\n\n> +verify_commit_encoding()\n> +{\n> ...\n> +}\n\nI am not sure if the protection these checks offer is worth the\ncomplexity of the script, but it is primarily to reduce back and\nforth between the l10n coordinator and the language teams, so I\nwon't complain.\n\n> +# vim: et ts=4 sw=4\n\nI prefer not to see scripts forcing author's personal preference.\nEspecially, wouldn't ts=4 make it hard to avoid indenting with runs\nof spaces by mistake?\n"},{"id":"186513","messageId":"CANYiYbGxsTZ1sDVf8e47w9butmN_XUgucJByfCdYfFSpNhzVYA@mail.gmail.com","threadId":"29870","inReplyTo":"7v399iddw3.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-09T00:57:22Z","receivedAt":"2012-03-09T00:57:22Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2012/3/9 Junio C Hamano <gitster@pobox.com>:\n> That's quite a style deviation from out norm in the commit log\n> messages, don't you think (see \"git log --no-merges -100\", for\n> example)?  State the problem you are attempting to solve first, and\n> explain the solution to the problem, in separate paragraphs for\n> readability, perhaps like this:\n>\n>        There are routine tasks translators need to perform that can\n>        be automated.\n>\n>        Help them to\n>\n>         (1) initialize or update the message files;\n>         (2) check errors in the message files they edited;\n>         (3) check errors in their commits; and\n>         (4) review recent updates to the message template file\n>             they base their translations on.\n>\n>        by adding a helper script.\n\nThank you for provide better commit log, and I learn\na lot from it. Writing in English still a big issue for me,\nand also obstacles to many l10n contributors. So your\ndecision that l10n contributors can write commit logs\nin native language is very helpful, yet it has potential\nrisk about wrong character encodings in commit log.\nSo I need to write a helper for l10n team leaders,\nespecially for myself, to detect bad commit log,\nbecause nobody knows all languages and encodings.\nHacks outside of \"po/\" directory should be checked\nregularly also.\n\n\n>> @@ -0,0 +1,271 @@\n>> +#!/bin/bash\n>\n> Is there any bash-ism in this script?  Otherwise please start this\n> with \"#!/bin/sh\" to allow people who do not use bash to get involved\n> in the project.\n\nThere are several regex match expressions written in bash style,\nwhich is not dash compatible. I will try to use grep and sed instead.\n\n> Will we later regret that we didn't give a command word for this\n> one?  Two common sources of such risks are:\n>\n>  (1) it turns out XX.po matches the pattern we would want to use as\n>     a command; and\n>\n>  (2) it turns out \"init/update\" is not the most often used action.\n>\n> I do not think (1) is likely. I do not think anybody can decide\n> about (2) at this point yet.\n\nThe style of arguments comes from previous Rakefile implementation.\nI will change XX.po as a alias subcommand of init/update.\n\n-- \nJiang xin\n"},{"id":"186526","messageId":"1331273307-64598-1-git-send-email-worldhello.net@gmail.com","threadId":"29870","inReplyTo":"7v399iddw3.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-09T06:08:27Z","receivedAt":"2012-03-09T06:08:27Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"There are routine tasks translators need to perform that can be automated.\nAdd a helper script which can help:\n\n - Initialize or update the message files;\n\n - Check errors in the message files they edited;\n\n - Check errors in their commits; and\n\n - Review recent updates to the message template file\n   they base their translations on.\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n po/po-helper.sh |  387 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 387 insertions(+)\n create mode 100755 po/po-helper.sh\n\ndiff --git a/po/po-helper.sh b/po/po-helper.sh\nnew file mode 100755\nindex 0000000..166ebb7\n--- /dev/null\n+++ b/po/po-helper.sh\n@@ -0,0 +1,387 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2012 Jiang Xin\n+\n+GIT=git\n+PODIR=$($GIT rev-parse --show-cdup)po\n+POTFILE=$PODIR/git.pot\n+\n+usage() {\n+\tcat <<-\\END_OF_USAGE\n+Maintaince script for l10n files and commits.\n+\n+Usage:\n+\n+ * po-helper.sh init XX.po\n+       Create the initial XX.po file in the po/ directory, where\n+       XX is the locale, e.g. \"de\", \"is\", \"pt_BR\", \"zh_CN\", etc.\n+\n+ * po-helper.sh update XX.po\n+       Update XX.po file(s) to the new git.pot template\n+\n+ * po-helper.sh check XX.po\n+       Perform syntax check on XX.po file(s)\n+\n+ * po-helper.sh check pot\n+       Display summary of updates/modifications of git.pot template\n+\n+ * po-helper.sh check commits [since] [til]\n+       Check non-ascii chars in commit logs\n+\n+       - don't write commit log with non-ascii chars without proper\n+         encoding settings;\n+\n+       - subject of commit log must written in English; and\n+\n+       - don't change files outside this directory (po/)\n+END_OF_USAGE\n+\n+\tif test $# -gt 0\n+\tthen\n+\t\techo\n+\t\techo \"Error: $*\"\n+\t\texit 1\n+\telse\n+\t\texit 0\n+\tfi\n+}\n+\n+# Init or update XX.po file from git.pot\n+update_po() {\n+\tif test $# -eq 0\n+\tthen\n+\t\tusage \"init/update needs at least one argument\"\n+\tfi\n+\twhile test $# -gt 0\n+\tdo\n+\t\tlocale=$(basename $1)\n+\t\tlocale=${locale%.po}\n+\t\tpo=$PODIR/$locale.po\n+\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n+\t\tif test -f $po\n+\t\tthen\n+\t\t\tmsgmerge --add-location --backup=off -U $po $POTFILE\n+\t\telse\n+\t\t\tmsginit -i $POTFILE --locale=$locale -o $po\n+\t\t\tperl -pi -e 's/(?<=\"Project-Id-Version: )PACKAGE VERSION/Git/' $po\n+\t\tfi\n+\t\tmkdir -p $(dirname $mo)\n+\t\tmsgfmt -o $mo --check --statistics $po\n+\t\tshift\n+\tdone\n+}\n+\n+notes_for_l10n_team_leader() {\n+\tlocale=$(basename $1)\n+\tlocale=${locale%.po}\n+\n+\tcat <<-END_OF_NOTES\n+\t============================================================\n+\tNotes for l10n team leader:\n+\n+\t    Since you create a initialial locale file, you are\n+\t    likely to be the leader of the $locale l10n team.\n+\n+\t    You can add your team infomation in the \"po/TEAMS\"\n+\t    file, and update it when necessary.\n+\n+\t    Please read the file \"po/README\" first to understand\n+\t    the workflow of Git l10n maintenance.\n+\t============================================================\n+\tEND_OF_NOTES\n+}\n+\n+# Check po, pot, commits\n+check() {\n+\tif test $# -eq 0\n+\tthen\n+\t\tls $PODIR/*.po |\n+\t\twhile read f\n+\t\tdo\n+\t\t\techo \"============================================================\"\n+\t\t\techo \"Check $(basename $f)...\"\n+\t\t\tcheck $f\n+\t\tdone\n+\n+\t\techo \"============================================================\"\n+\t\techo \"Check updates of git.pot...\"\n+\t\tcheck pot\n+\n+\t\techo \"============================================================\"\n+\t\techo \"Check commits...\"\n+\t\tcheck commits\n+\tfi\n+\twhile test $# -gt 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t*.po)\n+\t\t\tcheck_po $1\n+\t\t\t;;\n+\t\t*pot)\n+\t\t\tcheck_pot\n+\t\t\t;;\n+\t\tcommit|commits)\n+\t\t\tshift\n+\t\t\tcheck_commits $@\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tusage \"Unkown task \\\"$1\\\" for check\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+}\n+\n+# Syntax check on XX.po, or all .po files if nothing provided\n+check_po() {\n+\twhile test $# -gt 0\n+\tdo\n+\t\tlocale=$(basename $1)\n+\t\tlocale=${locale%.po}\n+\t\tpo=$PODIR/$locale.po\n+\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n+\t\tif test -f $po\n+\t\tthen\n+\t\t\tmkdir -p $(dirname $mo)\n+\t\t\tmsgfmt -o $mo --check --statistics $po\n+\t\telse\n+\t\t\techo \"Error: File $po does not exist.\" >&2\n+\t\tfi\n+\t\tshift\n+\tdone\n+}\n+\n+# Display summary of updates of git.pot\n+check_pot() {\n+\tpnew=\"^.*:\\([0-9]*\\): this message is used but not defined in.*\"\n+\tpdel=\"^.*:\\([0-9]*\\): warning: this message is not used.*\"\n+\tnew_count=0\n+\tdel_count=0\n+\tnew_lineno=\"\"\n+\tdel_lineno=\"\"\n+\n+\tstatus=$(cd $PODIR; $GIT status --porcelain -- $(basename $POTFILE))\n+\tif test -z \"$status\"\n+\tthen\n+\t\techo \"Nothing changed.\"\n+\telse\n+\t\ttmpfile=$(mktemp /tmp/git.po.XXXX)\n+\t\t(cd $PODIR; LANGUAGE=C $GIT show HEAD:./$(basename $POTFILE) > $tmpfile )\n+\t\tLANGUAGE=C msgcmp -N --use-untranslated $tmpfile $POTFILE 2>&1 | {\n+\t\t\twhile read line\n+\t\t\tdo\n+\t\t\t\tm=$(echo $line | grep \"$pnew\" | sed -e \"s/$pnew/\\1/\")\n+\t\t\t\tif test -n \"$m\"\n+\t\t\t\tthen\n+\t\t\t\t\tnew_count=$(( new_count + 1 ))\n+\t\t\t\t\tif test -z \"$new_lineno\"\n+\t\t\t\t\tthen\n+\t\t\t\t\t\tnew_lineno=\"$m\"\n+\t\t\t\t\telse\n+\t\t\t\t\t\tnew_lineno=\"${new_lineno}, $m\"\n+\t\t\t\t\tfi\n+\t\t\t\t\tcontinue\n+\t\t\t\tfi\n+\n+\t\t\t\tm=$(echo $line | grep \"$pdel\" | sed -e \"s/$pdel/\\1/\")\n+\t\t\t\tif test -n \"$m\"\n+\t\t\t\tthen\n+\t\t\t\t\tdel_count=$(( del_count + 1 ))\n+\t\t\t\t\tif test -z \"$del_lineno\"\n+\t\t\t\t\tthen\n+\t\t\t\t\t\tdel_lineno=\"$m\"\n+\t\t\t\t\telse\n+\t\t\t\t\t\tdel_lineno=\"${del_lineno}, $m\"\n+\t\t\t\t\tfi\n+\t\t\t\tfi\n+\t\t\tdone\n+\t\t\ttest $new_count -gt 1 && new_plur=\"s\" || new_plur=\"\"\n+\t\t\ttest $del_count -gt 1 && del_plur=\"s\" || del_plur=\"\"\n+\t\t\techo \"Updates of po/git.pot since last update:\"\n+\t\t\techo\n+\t\t\techo \" * Add ${new_count} new l10n message${new_plur}\" \\\n+\t\t\t\t \"in the new generated \\\"git.pot\\\" file at\" \\\n+\t\t\t\t \"line${new_plur}:\"\n+\t\t\techo \"   ${new_lineno}\"\n+\t\t\techo\n+\n+\t\t\techo \" * Remove ${del_count} l10n message${del_plur}\" \\\n+\t\t\t\t \"from the old \\\"git.pot\\\" file at line${del_plur}:\"\n+\t\t\techo \"   ${del_lineno}\"\n+\t\t}\n+\t\trm $tmpfile\n+\tfi\n+}\n+\n+verify_commit_encoding() {\n+\tc=$1\n+\tsubject=0\n+\tnon_ascii=\"\"\n+\tencoding=\"\"\n+\tlog=\"\"\n+\n+\t$GIT cat-file commit $c | {\n+\t\twhile read line\n+\t\tdo\n+\t\t\tlog=\"$log - $line\"\n+\t\t\t# next line would be the commit log subject line,\n+\t\t\t# if no previous empty line found.\n+\t\t\tif test -z \"$line\"\n+\t\t\tthen\n+\t\t\t\tsubject=$((subject + 1))\n+\t\t\t\tcontinue\n+\t\t\tfi\n+\t\t\tif test $subject -eq 0\n+\t\t\tthen\n+\t\t\t\tif echo $line | grep -q \"^encoding \"\n+\t\t\t\tthen\n+\t\t\t\t\tencoding=${line#encoding }\n+\t\t\t\tfi\n+\t\t\tfi\n+\t\t\t# non-ascii found in commit log\n+\t\t\tm=$(echo $line | sed -e \"s/\\([[:alnum:][:space:][:punct:]]\\)//g\")\n+\t\t\tif test -n \"$m\"\n+\t\t\tthen\n+\t\t\t\tnon_ascii=\"$m >> $line <<\"\n+\t\t\t\tif test $subject -eq 1\n+\t\t\t\tthen\n+\t\t\t\t\treport_nonascii_in_subject $c \"$non_ascii\"\n+\t\t\t\t\treturn\n+\t\t\t\tfi\n+\t\t\tfi\n+\t\t\t# subject has only one line\n+\t\t\ttest $subject -eq 1 && subject=$((subject += 1))\n+\t\t\t# break if there are non-asciis and has already checked subject line\n+\t\t\tif test -n \"$non_ascii\" && test $subject -gt 0\n+\t\t\tthen\n+\t\t\t\tbreak\n+\t\t\tfi\n+\t\tdone\n+\t\tif test -n \"$non_ascii\"\n+\t\tthen\n+\t\t\tif test -z \"$encoding\"\n+\t\t\tthen\n+\t\t\t\techo $line | iconv -f UTF-8 -t UTF-8 -s >/dev/null ||\n+\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\"\n+\t\t\telse\n+\t\t\t\techo $line | iconv -f $encoding -t UTF-8 -s >/dev/null ||\n+\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\" \"$encoding\"\n+\t\t\tfi\n+\t\tfi\n+\t}\n+}\n+\n+report_nonascii_in_subject() {\n+\tc=$1\n+\tnon_ascii=$2\n+\n+\techo \"============================================================\" >&2\n+\techo \"Error: Non-ASCII in subject of commit $c:\"                    >&2\n+\techo \"\t   ${non_ascii}\"                                            >&2\n+\techo\n+\t$GIT cat-file commit $c | head -15 |\n+\twhile read line\n+\tdo\n+\t\techo \"\\t$line\"                                              >&2\n+\tdone\n+\techo\n+}\n+\n+report_bad_encoding() {\n+\tc=$1\n+\tnon_ascii=$2\n+\tencoding=$3\n+\n+\techo \"============================================================\" >&2\n+\tif test -z \"$encoding\"\n+\tthen\n+\t\techo \"Error: Not have encoding setting for commit $c:\"      >&2\n+\telse\n+\t\techo \"Error: Wrong encoding ($encoding) for commit $c:\"     >&2\n+\tfi\n+\techo \"\t   ${non_ascii}\"                                            >&2\n+\techo                                                                >&2\n+\t$GIT cat-file commit $c | head -15 |\n+\twhile read line\n+\tdo\n+\t\techo \"\\t$line\"                                              >&2\n+\tdone\n+\techo\n+}\n+\n+# Check commit logs for bad encoding settings\n+check_commits() {\n+\tif test $# -gt 2\n+\tthen\n+\t\tusage \"check commits only needs 2 arguments\"\n+\tfi\n+\tsince=${1:-origin/master}\n+\ttil=${2:-HEAD}\n+\n+\tif $GIT diff-tree -r $since $til | awk '{print $6}' | grep -qv \"^po/\"\n+\tthen\n+\t\techo \"============================================================\" >&2\n+\t\techo \"Error: changed files outside po directory!\"           >&2\n+\t\techo \"\t   reference: git diff-tree -r $since $til\"         >&2\n+\tfi\n+\n+\tcount=0\n+\t$GIT rev-list ${since}..${til} | {\n+\t\twhile read c\n+\t\tdo\n+\t\t\tverify_commit_encoding $c\n+\t\t\tcount=$(( count + 1 ))\n+\t\tdone\n+\t\techo \"$count commits checked complete.\"\n+\t}\n+}\n+\n+\n+test $# -eq 0 && usage\n+\n+if ! test -f $POTFILE\n+then\n+\techo \"Cannot find git.pot in your workspace. Are you in the workspace of git project?\"\n+\texit 1\n+fi\n+\n+while test $# -ne 0\n+do\n+\tcase \"$1\" in\n+\tinit)\n+\t\tshift\n+\t\tupdate_po $1\n+\t\tnotes_for_l10n_team_leader $1\n+\t\tbreak\n+\t\t;;\n+\tupdate)\n+\t\tshift\n+\t\tupdate_po $@\n+\t\tbreak\n+\t\t;;\n+\tcheck)\n+\t\tshift\n+\t\tcheck $@\n+\t\tbreak\n+\t\t;;\n+\t*.po)\n+\t\tupdate_po $1\n+\t\t;;\n+\tpot|git.pot)\n+\t\tcheck pot\n+\t\t;;\n+\tcommit|commits)\n+\t\tshift\n+\t\tcheck commits $@\n+\t\tbreak\n+\t\t;;\n+\t-h|--help)\n+\t\tusage\n+\t\t;;\n+\t*)\n+\t\tusage \"Unknown command\"\n+\t\t;;\n+\tesac\n+\tshift\n+done\n-- \n1.7.9.2.330.gaa956.dirty\n"},{"id":"186527","messageId":"CAJDDKr7A1LN_r5v0yiacpEHTtEqQG2Hf=YZ6GbtsOHLadozDKA@mail.gmail.com","threadId":"29870","inReplyTo":"1331273307-64598-1-git-send-email-worldhello.net@gmail.com","subject":"Re: [PATCH v2] Maintaince script for l10n files and commits","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2012-03-09T06:20:51Z","receivedAt":"2012-03-09T06:20:51Z","isPatch":true,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"On Thu, Mar 8, 2012 at 10:08 PM, Jiang Xin <worldhello.net@gmail.com> wrote:\n> diff --git a/po/po-helper.sh b/po/po-helper.sh\n> new file mode 100755\n> index 0000000..166ebb7\n> --- /dev/null\n> +++ b/po/po-helper.sh\n> @@ -0,0 +1,387 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2012 Jiang Xin\n> +\n> +GIT=git\n\nI think it's customary to just write `git` in shell scripts.  It looks\nnicer then seeing $GIT everywhere, IMO.  I guess this could be helpful\nin the future but I don't see GIT being reassigned anywhere.\n\nCheers,\n-- \nDavid\n"},{"id":"186528","messageId":"CANYiYbEgrnB3yO2Gx=h=EGAfjpkTR78RjsbTP2ixsGB1fu5bog@mail.gmail.com","threadId":"29870","inReplyTo":"CAJDDKr7A1LN_r5v0yiacpEHTtEqQG2Hf=YZ6GbtsOHLadozDKA@mail.gmail.com","subject":"Re: [PATCH v2] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-09T06:31:36Z","receivedAt":"2012-03-09T06:31:36Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"2012/3/9 David Aguilar <davvid@gmail.com>:\n>> +\n>> +GIT=git\n>\n> I think it's customary to just write `git` in shell scripts.  It looks\n> nicer then seeing $GIT everywhere, IMO.  I guess this could be helpful\n> in the future but I don't see GIT being reassigned anywhere.\n\nJust for easy to find the git command called, nothing else.\n\n-- \nJiang Xin\n"},{"id":"186604","messageId":"7vhaxx2sqp.fsf@alter.siamese.dyndns.org","threadId":"29870","inReplyTo":"1331273307-64598-1-git-send-email-worldhello.net@gmail.com","subject":"Re: [PATCH v2] Maintaince script for l10n files and commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-03-10T00:40:30Z","receivedAt":"2012-03-10T00:40:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jiang Xin <worldhello.net@gmail.com> writes:\n\n> diff --git a/po/po-helper.sh b/po/po-helper.sh\n> new file mode 100755\n> index 0000000..166ebb7\n> --- /dev/null\n> +++ b/po/po-helper.sh\n> @@ -0,0 +1,387 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2012 Jiang Xin\n> +\n> +GIT=git\n> +PODIR=$($GIT rev-parse --show-cdup)po\n\nDavid already pointed out that $GIT is a bad style.\n\n> +POTFILE=$PODIR/git.pot\n> +\n> +usage() {\n\nStyle:\n\n\tusage () {\n\nI won't repeat this anymore in this message but there are others.\n\n> +# Init or update XX.po file from git.pot\n> +update_po() {\n> +\tif test $# -eq 0\n> +\tthen\n> +\t\tusage \"init/update needs at least one argument\"\n> +\tfi\n> +\twhile test $# -gt 0\n> +\tdo\n> +\t\tlocale=$(basename $1)\n> +\t\tlocale=${locale%.po}\n\nThis is bad for two reasons. (1) Your $1 that directly comes from\nthe end user's command line may have $IFS characters; (2) You do not\nhave to spawn a separate process to run basename.\n\nBut if I were writing this loop, I would probably avoided refering\nto \"$1\" and shifting at the end by starting it like so:\n\n\tfor locale\n        do\n                locale=${locale##*/}\n                locale=${locale%.po}\n\t\t...\n\tdone\n\n> +\t\tpo=$PODIR/$locale.po\n> +\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n> +\t\tif test -f $po\n\nIt is safer to say\n\n\tif test -f \"$po\"\n\nhere, even though it is not needed in the current form of this\nscript. Later somebody may change the definition of PODIR above to\nsomething else that may contain $IFS.\n\n> +\t\tthen\n> +\t\t\tmsgmerge --add-location --backup=off -U $po $POTFILE\n\nLikewise, both for \"$po\" and \"$POTFILE\" (I won't repeat this anymore\nin this message but there are others).\n\n> +}\n> +\n> +notes_for_l10n_team_leader() {\n> +\tlocale=$(basename $1)\n> +\tlocale=${locale%.po}\n\nLikewise. I won't repeat this anymore in this message but there are others.\n\n> +# Check po, pot, commits\n> +check() {\n> +\tif test $# -eq 0\n> +\tthen\n> +\t\tls $PODIR/*.po |\n> +\t\twhile read f\n> +\t\tdo\n> +\t\t\techo \"============================================================\"\n> +\t\t\techo \"Check $(basename $f)...\"\n> +\t\t\tcheck $f\n> +\t\tdone\n> +\n> +\t\techo \"============================================================\"\n> +\t\techo \"Check updates of git.pot...\"\n> +\t\tcheck pot\n> +\n> +\t\techo \"============================================================\"\n> +\t\techo \"Check commits...\"\n> +\t\tcheck commits\n> +\tfi\n> +\twhile test $# -gt 0\n> +\tdo\n> +\t\tcase \"$1\" in\n> +\t\t*.po)\n> +\t\t\tcheck_po $1\n> +\t\t\t;;\n> +\t\t*pot)\n\nThis is yucky.\n\n\t\tpot | git.pot)\n\nwould have been easier to understand what is going on.  Either we\nreached here from \"check pot\" when this function was called without\nargument, or we were fed the git.pot from the command line.\n\n> +\t\t\tcheck_pot\n> +\t\t\t;;\n> +\t\tcommit|commits)\n> +\t\t\tshift\n> +\t\t\tcheck_commits $@\n> +\t\t\tbreak\n> +\t\t\t;;\n\nPerhaps you meant to say\n\n\tcheck_commits \"$@\"\n\n> +\t\t*)\n> +\t\t\tusage \"Unkown task \\\"$1\\\" for check\"\n> +\t\t\t;;\n\nI think we tend to do\n\n\tusage \"Unknown task '$1' for check\"\n\n> +# Syntax check on XX.po, or all .po files if nothing provided\n> +check_po() {\n> +\twhile test $# -gt 0\n> +\tdo\n> +\t\tlocale=$(basename $1)\n> +\t\tlocale=${locale%.po}\n> +\t\tpo=$PODIR/$locale.po\n> +\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n> +\t\tif test -f $po\n> +\t\tthen\n> +\t\t\tmkdir -p $(dirname $mo)\n> +\t\t\tmsgfmt -o $mo --check --statistics $po\n> +\t\telse\n> +\t\t\techo \"Error: File $po does not exist.\" >&2\n\nIt would make it more obvious that this error message does go to\nthe standard error stream if you said it like this:\n\n\techo >&2 \"Error: File '$po' does not exist.\"\n\n> +\t\tfi\n> +\t\tshift\n> +\tdone\n> +}\n\nAgain,\n\n\tfor locale\n        do\n        \t...\n\tdone\n\nwould have made the loop easier (less risk forgetting to shift or\nto shift too many).\n\n> +# Display summary of updates of git.pot\n> +check_pot() {\n> +\tpnew=\"^.*:\\([0-9]*\\): this message is used but not defined in.*\"\n> +\tpdel=\"^.*:\\([0-9]*\\): warning: this message is not used.*\"\n> +\tnew_count=0\n> +\tdel_count=0\n> +\tnew_lineno=\"\"\n> +\tdel_lineno=\"\"\n> +\n> +\tstatus=$(cd $PODIR; $GIT status --porcelain -- $(basename $POTFILE))\n> +\tif test -z \"$status\"\n> +\tthen\n> +\t\techo \"Nothing changed.\"\n> +\telse\n> +\t\ttmpfile=$(mktemp /tmp/git.po.XXXX)\n\n(optional) perhaps set a trap to remove this here, instead of an\nexplicit \"rm\" at the end?\n\n> +\t\t(cd $PODIR; LANGUAGE=C $GIT show HEAD:./$(basename $POTFILE) > $tmpfile )\n\n\t\t... show HEAD:./${POTFILE##*/} >\"$tmpfile\"\n\nLook for \"Redirection operators\" in Documentation/CodingGuidelines.\n\n> +\t\tLANGUAGE=C msgcmp -N --use-untranslated $tmpfile $POTFILE 2>&1 | {\n> +\t\t\twhile read line\n> +\t\t\tdo\n> +\t\t\t\tm=$(echo $line | grep \"$pnew\" | sed -e \"s/$pnew/\\1/\")\n\nMake it a habit to suspect that you are using one process too many,\nwhenever you see grep and sed in the same pipe.\n\n\t... | sed -ne \"s/$pnew/\\1/\"\n\nwould be sufficient, no?\n\n> +\t\t\t\tif test -n \"$m\"\n> +\t\t\t\tthen\n> +\t\t\t\t\tnew_count=$(( new_count + 1 ))\n> +\t\t\t\t\tif test -z \"$new_lineno\"\n> +\t\t\t\t\tthen\n> +\t\t\t\t\t\tnew_lineno=\"$m\"\n> +\t\t\t\t\telse\n> +\t\t\t\t\t\tnew_lineno=\"${new_lineno}, $m\"\n> +\t\t\t\t\tfi\n> +\t\t\t\t\tcontinue\n> +\t\t\t\tfi\n> +\n> +\t\t\t\tm=$(echo $line | grep \"$pdel\" | sed -e \"s/$pdel/\\1/\")\n> +\t\t\t\tif test -n \"$m\"\n> +\t\t\t\tthen\n> +\t\t\t\t\tdel_count=$(( del_count + 1 ))\n> +\t\t\t\t\tif test -z \"$del_lineno\"\n> +\t\t\t\t\tthen\n> +\t\t\t\t\t\tdel_lineno=\"$m\"\n> +\t\t\t\t\telse\n> +\t\t\t\t\t\tdel_lineno=\"${del_lineno}, $m\"\n> +\t\t\t\t\tfi\n> +\t\t\t\tfi\n> +\t\t\tdone\n> +\t\t\ttest $new_count -gt 1 && new_plur=\"s\" || new_plur=\"\"\n> +\t\t\ttest $del_count -gt 1 && del_plur=\"s\" || del_plur=\"\"\n\nIsn't plural forms \"0 lines, 1 line, 2 lines,...\"?  We have this in\nour \"gettext.h\" that says \"use singular form only when n is 1\", not\n\"when n is less than 2\":\n\n\t#define ngettext(s, p, n) ((n == 1) ? (s) : (p))\n\n> +verify_commit_encoding() {\n> +\tc=$1\n> +\tsubject=0\n> +\tnon_ascii=\"\"\n> +\tencoding=\"\"\n> +\tlog=\"\"\n> +\n> +\t$GIT cat-file commit $c | {\n> +\t\twhile read line\n\nAt least, you should read with \"read -r\", if you were to write this\nas a shell script.\n\n> +\t\tdo\n> +\t\t\tlog=\"$log - $line\"\n> +\t\t\t# next line would be the commit log subject line,\n> +\t\t\t# if no previous empty line found.\n> +\t\t\tif test -z \"$line\"\n> +\t\t\tthen\n> +\t\t\t\tsubject=$((subject + 1))\n\nEven though POSIX allows the above, this is preferred:\n\n\tsubject=$(( $subject + 1 ))\n\nas some shells were reported to barf without $ in front of the\nvariable names.\n\n> +\t\t\t\tcontinue\n> +\t\t\tfi\n> +\t\t\tif test $subject -eq 0\n> +\t\t\tthen\n> +\t\t\t\tif echo $line | grep -q \"^encoding \"\n> +\t\t\t\tthen\n> +\t\t\t\t\tencoding=${line#encoding }\n> +\t\t\t\tfi\n\n\tcase \"$line\" in\n        encoding' '*)\n\t\tencoding=${...}\n\t\t;;\n\tesac\n\n> +\t\t\tfi\n> +\t\t\t# non-ascii found in commit log\n> +\t\t\tm=$(echo $line | sed -e \"s/\\([[:alnum:][:space:][:punct:]]\\)//g\")\n> +\t\t\tif test -n \"$m\"\n> +\t\t\tthen\n> +\t\t\t\tnon_ascii=\"$m >> $line <<\"\n> +\t\t\t\tif test $subject -eq 1\n> +\t\t\t\tthen\n> +\t\t\t\t\treport_nonascii_in_subject $c \"$non_ascii\"\n> +\t\t\t\t\treturn\n> +\t\t\t\tfi\n> +\t\t\tfi\n> +\t\t\t# subject has only one line\n> +\t\t\ttest $subject -eq 1 && subject=$((subject += 1))\n\nsubject=$(( $subject + 1 ))\n\n> +\t\t\t# break if there are non-asciis and has already checked subject line\n> +\t\t\tif test -n \"$non_ascii\" && test $subject -gt 0\n> +\t\t\tthen\n> +\t\t\t\tbreak\n\nIs it OK for the body to have good line followed by a bad line?\n\n> +\t\t\tfi\n> +\t\tdone\n> +\t\tif test -n \"$non_ascii\"\n> +\t\tthen\n> +\t\t\tif test -z \"$encoding\"\n> +\t\t\tthen\n> +\t\t\t\techo $line | iconv -f UTF-8 -t UTF-8 -s >/dev/null ||\n> +\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\"\n> +\t\t\telse\n> +\t\t\t\techo $line | iconv -f $encoding -t UTF-8 -s >/dev/null ||\n> +\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\" \"$encoding\"\n> +\t\t\tfi\n> +\t\tfi\n> +\t}\n> +}\n"},{"id":"186619","messageId":"1331371049-37208-1-git-send-email-worldhello.net@gmail.com","threadId":"29870","inReplyTo":"7v399iddw3.fsf@alter.siamese.dyndns.org","subject":"[PATCH v3] Maintaince script for l10n files and commits","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2012-03-10T09:17:29Z","receivedAt":"2012-03-10T09:17:29Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"There are routine tasks translators need to perform that can be automated.\nAdd a helper script which can help:\n\n - Initialize or update the message files;\n\n - Check errors in the message files they edited;\n\n - Check errors in their commits; and\n\n - Review recent updates to the message template file\n   they base their translations on.\n\nSigned-off-by: Jiang Xin <worldhello.net@gmail.com>\n---\n po/po-helper.sh |  411 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 411 insertions(+)\n create mode 100755 po/po-helper.sh\n\ndiff --git a/po/po-helper.sh b/po/po-helper.sh\nnew file mode 100755\nindex 0000000..2398f52\n--- /dev/null\n+++ b/po/po-helper.sh\n@@ -0,0 +1,411 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2012 Jiang Xin\n+\n+PODIR=$(git rev-parse --show-cdup)po\n+POTFILE=$PODIR/git.pot\n+\n+usage () {\n+\tcat <<-\\END_OF_USAGE\n+Maintaince script for l10n files and commits.\n+\n+Usage:\n+\n+ * po-helper.sh init XX.po\n+       Create the initial XX.po file in the po/ directory, where\n+       XX is the locale, e.g. \"de\", \"is\", \"pt_BR\", \"zh_CN\", etc.\n+\n+ * po-helper.sh update XX.po ...\n+       Update XX.po file(s) from the new git.pot template\n+\n+ * po-helper.sh check XX.po ...\n+       Perform syntax check on XX.po file(s)\n+\n+ * po-helper.sh check commits [ <since> <til> ]\n+       Check proper encoding of non-ascii chars in commit logs\n+\n+       - don't write commit log with non-ascii chars without proper\n+         encoding settings;\n+\n+       - subject of commit log must written in English; and\n+\n+       - don't change files outside this directory (po/)\n+\n+ * po-helper.sh diff [ <old> <new> ]\n+       Show difference between old and new po/pot files.\n+       Default show changes of git.pot since last update.\n+END_OF_USAGE\n+\n+\tif test $# -gt 0\n+\tthen\n+\t\techo >&2\n+\t\techo >&2 \"Error: $*\"\n+\t\texit 1\n+\telse\n+\t\texit 0\n+\tfi\n+}\n+\n+# Init or update XX.po file from git.pot\n+update_po () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tusage \"init/update needs at least one argument\"\n+\tfi\n+\tfor locale\n+\tdo\n+\t\tlocale=${locale##*/}\n+\t\tlocale=${locale%.po}\n+\t\tpo=$PODIR/$locale.po\n+\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n+\t\tif test -n \"$locale\"\n+\t\tthen\n+\t\t\tif test -f \"$po\"\n+\t\t\tthen\n+\t\t\t\tmsgmerge --add-location --backup=off -U \"$po\" \"$POTFILE\"\n+\t\t\t\tmkdir -p \"${mo%/*}\"\n+\t\t\t\tmsgfmt -o \"$mo\" --check --statistics \"$po\"\n+\t\t\telse\n+\t\t\t\tmsginit -i \"$POTFILE\" --locale=\"$locale\" -o \"$po\"\n+\t\t\t\tperl -pi -e 's/(?<=\"Project-Id-Version: )PACKAGE VERSION/Git/' \"$po\"\n+\t\t\t\tnotes_for_l10n_team_leader \"$locale\"\n+\t\t\tfi\n+\t\tfi\n+\tdone\n+}\n+\n+notes_for_l10n_team_leader () {\n+\tcat <<-END_OF_NOTES\n+\t============================================================\n+\tNotes for l10n team leader:\n+\n+\t    Since you create a initialial locale file, you are\n+\t    likely to be the leader of the $1 l10n team.\n+\n+\t    You can add your team infomation in the \"po/TEAMS\"\n+\t    file, and update it when necessary.\n+\n+\t    Please read the file \"po/README\" first to understand\n+\t    the workflow of Git l10n maintenance.\n+\t============================================================\n+\tEND_OF_NOTES\n+}\n+\n+# Check po files and commits. Run all checks if no argument is given.\n+check () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tls $PODIR/*.po |\n+\t\twhile read f\n+\t\tdo\n+\t\t\techo \"============================================================\"\n+\t\t\techo \"Check ${f##*/}...\"\n+\t\t\tcheck \"$f\"\n+\t\tdone\n+\n+\t\techo \"============================================================\"\n+\t\techo \"Show updates of git.pot...\"\n+\t\tshow_diff\n+\n+\t\techo \"============================================================\"\n+\t\techo \"Check commits...\"\n+\t\tcheck commits\n+\tfi\n+\twhile test $# -gt 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t*.po)\n+\t\t\tcheck_po \"$1\"\n+\t\t\t;;\n+\t\tcommit | commits)\n+\t\t\tshift\n+\t\t\tcheck_commits \"$@\"\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tusage \"Unkown task '$1' for check\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+}\n+\n+# Syntax check on XX.po\n+check_po () {\n+\tfor locale\n+\tdo\n+\t\tlocale=${locale##*/}\n+\t\tlocale=${locale%.po}\n+\t\tpo=$PODIR/$locale.po\n+\t\tmo=$PODIR/build/locale/$locale/LC_MESSAGES/git.mo\n+\t\tif test -n \"$locale\"\n+\t\tthen\n+\t\t\tif test -f \"$po\"\n+\t\t\tthen\n+\t\t\t\tmkdir -p \"${mo%/*}\"\n+\t\t\t\tmsgfmt -o \"$mo\" --check --statistics \"$po\"\n+\t\t\telse\n+\t\t\t\techo >&2 \"Error: File $po does not exist.\"\n+\t\t\tfi\n+\t\tfi\n+\tdone\n+}\n+\n+# Show summary of updates of git.pot or difference between two po/pot files.\n+show_diff () {\n+\tpnew=\"^.*:\\([0-9]*\\): this message is used but not defined in.*\"\n+\tpdel=\"^.*:\\([0-9]*\\): warning: this message is not used.*\"\n+\tnew_count=0\n+\tdel_count=0\n+\tnew_lines=\n+\tdel_lines=\n+\n+\tcase $# in\n+\t0)\n+\t\tstatus=$(cd $PODIR; git status --porcelain -- ${POTFILE##*/})\n+\t\tif test -z \"$status\"\n+\t\tthen\n+\t\t\techo \"Nothing changed.\"\n+\t\t\treturn 0\n+\t\tfi\n+\t\ttmpfile=$(mktemp /tmp/git.po.XXXX)\n+\t\t(cd $PODIR; LANGUAGE=C git show HEAD:./${POTFILE##*/} >\"$tmpfile\")\n+\t\toldpot=$tmpfile\n+\t\tnewpot=$POTFILE\n+\t\toldtitle=\"the old 'git.pot' file\"\n+\t\tnewtitle=\"the new generated 'git.pot' file\"\n+\t\t# Remove tmpfile on exit\n+\t\ttrap 'rm -f \"$tmpfile\"' 0\n+\t\techo \"Changes of po/git.pot since last update:\"\n+\t\t;;\n+\t2)\n+\t\toldpot=$1\n+\t\tnewpot=$2\n+\t\toldtitle=${oldpot##*/}\n+\t\tnewtitle=${newpot##*/}\n+\t\techo \"Difference between $oldtitle and $newtitle:\"\n+\t\t;;\n+\t*)\n+\t\tusage \"show_diff takes 2 or null arguments.\"\n+\t\t;;\n+\tesac\n+\n+\tLANGUAGE=C msgcmp -N --use-untranslated \"$oldpot\" \"$newpot\" 2>&1 | {\n+\t\twhile read line\n+\t\tdo\n+\t\t\t# Extract line number \"NNN\"from output, like:\n+\t\t\t#     git.pot:NNN: this message is used but not defined in /tmp/git.po.XXXX\n+\t\t\tm=$(echo $line | grep \"$pnew\" | sed -e \"s/$pnew/\\1/\")\n+\t\t\tif test -n \"$m\"\n+\t\t\tthen\n+\t\t\t\tnew_count=$(( new_count + 1 ))\n+\t\t\t\tif test -z \"$new_lines\"\n+\t\t\t\tthen\n+\t\t\t\t\tnew_lines=\"$m\"\n+\t\t\t\telse\n+\t\t\t\t\tnew_lines=\"${new_lines}, $m\"\n+\t\t\t\tfi\n+\t\t\t\tcontinue\n+\t\t\tfi\n+\n+\t\t\t# Extract line number \"NNN\" from output, like:\n+\t\t\t#     /tmp/git.po.XXXX:NNN: warning: this message is not used\n+\t\t\tm=$(echo $line | grep \"$pdel\" | sed -e \"s/$pdel/\\1/\")\n+\t\t\tif test -n \"$m\"\n+\t\t\tthen\n+\t\t\t\tdel_count=$(( del_count + 1 ))\n+\t\t\t\tif test -z \"$del_lines\"\n+\t\t\t\tthen\n+\t\t\t\t\tdel_lines=\"$m\"\n+\t\t\t\telse\n+\t\t\t\t\tdel_lines=\"${del_lines}, $m\"\n+\t\t\t\tfi\n+\t\t\tfi\n+\t\tdone\n+\t\tif test $new_count -eq 0 && test $del_count -eq 0\n+\t\tthen\n+\t\t\techo \"Nothing changed.\"\n+\t\t\treturn 0\n+\t\tfi\n+\t\tif test $new_count -gt 0\n+\t\tthen\n+\t\t\ttest $new_count -ne 1 && new_plur=\"s\" || new_plur=\"\"\n+\t\t\techo\n+\t\t\techo \" * Add ${new_count} new l10n message${new_plur}\" \\\n+\t\t\t\t \"in $newtitle at\" \\\n+\t\t\t\t \"line${new_plur}:\"\n+\t\t\techo \"   ${new_lines}\"\n+\t\tfi\n+\t\tif test $del_count -gt 0\n+\t\tthen\n+\t\t\ttest $del_count -ne 1 && del_plur=\"s\" || del_plur=\"\"\n+\t\t\techo\n+\t\t\techo \" * Remove ${del_count} l10n message${del_plur}\" \\\n+\t\t\t\t \"from $oldtitle at line${del_plur}:\"\n+\t\t\techo \"   ${del_lines}\"\n+\t\tfi\n+\t}\n+}\n+\n+verify_commit_encoding () {\n+\tc=$1\n+\tsubject=0\n+\tnon_ascii=\"\"\n+\tencoding=\"\"\n+\tlog=\"\"\n+\n+\tgit cat-file commit $c | {\n+\t\twhile read line\n+\t\tdo\n+\t\t\tlog=\"$log - $line\"\n+\t\t\t# next line would be the commit log subject line,\n+\t\t\t# if no previous empty line found.\n+\t\t\tif test -z \"$line\"\n+\t\t\tthen\n+\t\t\t\tsubject=$(( subject + 1 ))\n+\t\t\t\tcontinue\n+\t\t\tfi\n+\t\t\tif test $subject -eq 0\n+\t\t\tthen\n+\t\t\t\tif echo $line | grep -q \"^encoding \"\n+\t\t\t\tthen\n+\t\t\t\t\tencoding=${line#encoding }\n+\t\t\t\tfi\n+\t\t\tfi\n+\t\t\t# non-ascii found in commit log\n+\t\t\tm=$(echo $line | sed -e \"s/\\([[:alnum:][:space:][:punct:]]\\)//g\")\n+\t\t\tif test -n \"$m\"\n+\t\t\tthen\n+\t\t\t\tnon_ascii=\"$m >> $line <<\"\n+\t\t\t\tif test $subject -eq 1\n+\t\t\t\tthen\n+\t\t\t\t\treport_nonascii_in_subject $c \"$non_ascii\"\n+\t\t\t\t\treturn\n+\t\t\t\tfi\n+\t\t\tfi\n+\t\t\t# subject has only one line\n+\t\t\ttest $subject -eq 1 && subject=$(( subject + 1 ))\n+\t\t\t# break if there are non-asciis and has already checked subject line\n+\t\t\tif test -n \"$non_ascii\" && test $subject -gt 0\n+\t\t\tthen\n+\t\t\t\tbreak\n+\t\t\tfi\n+\t\tdone\n+\t\tif test -n \"$non_ascii\"\n+\t\tthen\n+\t\t\tif test -z \"$encoding\"\n+\t\t\tthen\n+\t\t\t\techo $line | iconv -f UTF-8 -t UTF-8 -s >/dev/null ||\n+\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\"\n+\t\t\telse\n+\t\t\t\techo $line | iconv -f $encoding -t UTF-8 -s >/dev/null ||\n+\t\t\t\t\treport_bad_encoding \"$c\" \"$non_ascii\" \"$encoding\"\n+\t\t\tfi\n+\t\tfi\n+\t}\n+}\n+\n+report_nonascii_in_subject () {\n+\tc=$1\n+\tnon_ascii=$2\n+\n+\techo >&2 \"============================================================\"\n+\techo >&2 \"Error: Non-ASCII in subject of commit $c:\"\n+\techo >&2 \"       ${non_ascii}\"\n+\techo >&2\n+\tgit cat-file commit \"$c\" | head -15 |\n+\twhile read line\n+\tdo\n+\t\techo >&2 \"\\t$line\"\n+\tdone\n+\techo >&2\n+}\n+\n+report_bad_encoding () {\n+\tc=$1\n+\tnon_ascii=$2\n+\tencoding=$3\n+\n+\techo >&2 \"============================================================\"\n+\tif test -z \"$encoding\"\n+\tthen\n+\t\techo >&2 \"Error: Not have encoding setting for commit $c:\"\n+\telse\n+\t\techo >&2 \"Error: Wrong encoding ($encoding) for commit $c:\"\n+\tfi\n+\techo >&2 \"       ${non_ascii}\"\n+\techo >&2\n+\tgit cat-file commit \"$c\" | head -15 |\n+\twhile read line\n+\tdo\n+\t\techo >&2 \"\\t$line\"\n+\tdone\n+\techo\n+}\n+\n+# Check commit logs for bad encoding settings\n+check_commits () {\n+\tif test $# -gt 2\n+\tthen\n+\t\tusage \"check commits only needs 2 arguments\"\n+\tfi\n+\tsince=${1:-origin/master}\n+\ttil=${2:-HEAD}\n+\n+\tif git diff-tree -r \"$since\" \"$til\" | awk '{print $6}' | grep -qv \"^po/\"\n+\tthen\n+\t\techo >&2 \"============================================================\"\n+\t\techo >&2 \"Error: changed files outside po directory!\"\n+\t\techo >&2 \"       reference: git diff-tree -r $since $til\"\n+\tfi\n+\n+\tcount=0\n+\tgit rev-list ${since}..${til} | {\n+\t\twhile read c\n+\t\tdo\n+\t\t\tverify_commit_encoding $c\n+\t\t\tcount=$(( count + 1 ))\n+\t\tdone\n+\t\techo \"$count commits checked complete.\"\n+\t}\n+}\n+\n+\n+test $# -eq 0 && usage\n+\n+if ! test -f \"$POTFILE\"\n+then\n+\techo \"Cannot find git.pot in your workspace. Are you in the workspace of git project?\"\n+\texit 1\n+fi\n+\n+while test $# -ne 0\n+do\n+\tcase \"$1\" in\n+\tinit | update)\n+\t\tshift\n+\t\tupdate_po \"$@\"\n+\t\tbreak\n+\t\t;;\n+\tcheck)\n+\t\tshift\n+\t\tcheck \"$@\"\n+\t\tbreak\n+\t\t;;\n+\tdiff)\n+\t\tshift\n+\t\tshow_diff \"$@\"\n+\t\tbreak\n+\t\t;;\n+\t*.po)\n+\t\tupdate_po \"$1\"\n+\t\t;;\n+\t-h | --help)\n+\t\tusage\n+\t\t;;\n+\t*)\n+\t\tusage \"Unknown command '$1'.\"\n+\t\t;;\n+\tesac\n+\tshift\n+done\n-- \n1.7.9.2.330.gaa956.dirty\n"}]}