1#!/usr/bin/env python
2
3# This file is part of LilyPond, the GNU music typesetter.
4#
5# Copyright (C) 2007--2020 John Mandereau <john.mandereau@gmail.com>
6#
7# LilyPond is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# LilyPond is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19
20import __main__
21import optparse
22import os
23import sys
24import re
25
26import langdefs
27import buildlib
28
29verbose = 0
30use_colors = False
31lang = 'C'
32C = lang
33
34
35def dir_lang(file, lang, lang_dir_index):
36    path_components = file.split('/')
37    path_components[lang_dir_index] = lang
38    return os.path.join(*path_components)
39
40
41# ugh, this is complicated; where has the good old 'git rev-parse' gone?
42vc_revision_parse = 'git log -1 --pretty=format:%%H %s'
43
44
45def do_file(file_name, lang_codes):
46    if verbose:
47        sys.stderr.write('%s...\n' % file_name)
48    split_file_name = file_name.split('/')
49    d1, d2 = split_file_name[0:2]
50    if d1 in lang_codes:
51        check_lang = d1
52        lang_dir_index = 0
53    elif d2 in lang_codes:
54        check_lang = d2
55        lang_dir_index = 1
56    else:
57        check_lang = lang
58    if check_lang == C:
59        raise Exception('cannot determine language for ' + file_name)
60    else:
61        if os.path.splitext(file_name)[1] == '.texidoc':
62            original = file_name.replace(os.path.join(
63                check_lang, 'texidocs'), 'snippets', 1)
64            original = original.replace('.texidoc', '.ly', 1)
65        else:
66            original = dir_lang(file_name, 'en', lang_dir_index)
67        translated_contents = open(file_name, encoding='utf8').read()
68
69        # experimental feature
70        if not touch_committishes in (current_revision, 'HEAD'):
71            (changes_in_original, error) = \
72                buildlib.check_translated_doc(original,
73                                              file_name,
74                                              translated_contents,
75                                              upper_revision=touch_committishes)
76            if not error and not changes_in_original in ('', '\n'):
77                translated_contents = \
78                    buildlib.revision_re.sub('GIT committish: ' + current_revision,
79                                             translated_contents, 1)
80                f = open(file_name, 'w', encoding='utf8').write(translated_contents)
81                return
82
83    (diff_string, error) \
84        = buildlib.check_translated_doc(original,
85                                        file_name,
86                                        translated_contents,
87                                        color=use_colors and not update_mode)
88
89    if error:
90        sys.stderr.write('warning: %s: %s' % (file_name, error))
91
92    if update_mode:
93        if error or len(diff_string) >= os.path.getsize(original):
94            buildlib.read_pipe(text_editor + ' ' + file_name + ' ' + original)
95        elif diff_string:
96            diff_file = original + '.diff'
97            f = open(diff_file, 'w', encoding='utf8')
98            f.write(diff_string)
99            f.close()
100            buildlib.read_pipe(text_editor + ' ' + file_name + ' ' + diff_file)
101            os.remove(diff_file)
102    else:
103        sys.stdout.write(diff_string)
104
105
106def usage():
107    sys.stdout.write(r'''
108Usage:
109check-translation [--language=LANG] [--verbose] [--update] [-t COMMIT] FILE...
110''')
111
112
113def do_options():
114    global lang, verbose, update_mode, touch_committishes, use_colors
115
116    p = optparse.OptionParser(usage="check-translation [--language=LANG] [--verbose] [--update] [-t COMMIT] FILE...",
117                              description="")
118    p.add_option("--language",
119                 action='store',
120                 default=C,
121                 dest="language",
122                 metavar='LL',
123                 help="assume document language ISO 639 code LL by default")
124    p.add_option("--no-color",
125                 action='store_false',
126                 default=True,
127                 dest="color",
128                 help="do not print ANSI-colored output")
129    p.add_option("--verbose",
130                 action='store_true',
131                 default=False,
132                 dest="verbose",
133                 help="print details, including executed shell commands")
134    p.add_option('-t',
135                 action='store',
136                 default='HEAD',
137                 dest="touch_committishes",
138                 metavar='COMMIT',
139                 help='[EXPERIMENTAL] update committishes of all files that were up to \
140date at commit COMMIT')
141    p.add_option('-u', "--update",
142                 action='store_true',
143                 default=False,
144                 dest='update_mode',
145                 help='call $EDITOR to update the translation')
146
147    (options, files) = p.parse_args()
148    verbose = options.verbose
149    lang = options.language
150    use_colors = options.color
151    update_mode = options.update_mode
152    touch_committishes = options.touch_committishes
153
154    return files
155
156
157def main():
158    global update_mode, text_editor, touch_committishes, current_revision
159
160    files = do_options()
161    if 'EDITOR' in os.environ:
162        text_editor = os.environ['EDITOR']
163    else:
164        update_mode = False
165    buildlib.verbose = verbose
166    (parsed_revision, error) = buildlib.read_pipe(
167        vc_revision_parse % touch_committishes)
168    if error:
169        sys.stderr.write('warning: %s' % error)
170    else:
171        touch_committishes = parsed_revision.strip()
172    current_revision = buildlib.read_pipe(vc_revision_parse % 'HEAD')[0]
173
174    for i in files:
175        do_file(i, list(langdefs.LANGDICT.keys()))
176
177
178if __name__ == '__main__':
179    main()
180