LSR: Update.
[lilypond.git] / buildscripts / update-snippets.py
blob6b70c79467b50bb3084efe6a401cb60c597658b5
1 #!@PYTHON@
2 # update-snippets.py
4 # USAGE: update-snippets.py REFERENCE-DIR TARGET-DIR FILES
6 # update ly snippets in TARGET-DIR/FILES with snippets from REFERENCE-DIR/FILES
8 # More precisely, each existing FILE in TARGET-DIR is matched to the FILE in
9 # REFERENCE-DIR (it the latter does not exist, a warning is given).
11 # Shell wildcards expansion is performed on FILES.
12 # This script currently supports Texinfo format.
13 # Ly snippets preceded with a line containing '@c KEEP LY' in TARGET-DIR/FILES
14 # will not be updated.
15 # An error occurs if REFERENCE-DIR/FILE and TARGET-DIR/FILE do not have the
16 # same snippets count.
18 import sys
19 import os
20 import glob
21 import re
23 print "update-snippets.py"
25 comment_re = re.compile (r'(?<!@)(@c(?:omment)? .*?\n|^@ignore\n.*?\n@end ignore\n)', re.M | re.S)
26 snippet_re = re.compile (r'^(@lilypond(?:file)?(?:\[.*?\])?\s*\{.+?\}|@lilypond(?:\[.*?\])?(?:.|\n)+?@end lilypond)', re.M)
29 def snippet_split (l):
30 r = []
31 for s in [s for s in l if s]:
32 if s.startswith ('@c ') or s.startswith ('@ignore\n') or s.startswith ('@comment '):
33 r.append(s)
34 else:
35 r += [t for t in snippet_re.split (s) if t]
36 return r
38 def count_snippet (l):
39 k = 0
40 for s in l:
41 if s.startswith ('@lilypond'):
42 k += 1
43 return k
45 def find_next_snippet (l, k):
46 while not l[k].startswith ('@lilypond'):
47 k += 1
48 return k
50 exit_code = 0
52 def update_exit_code (code):
53 global exit_code
54 exit_code = max (code, exit_code)
56 ref_dir, target_dir = sys.argv [1:3]
57 file_patterns = sys.argv[3:]
59 total_snippet_count = 0
60 changed_snippets_count = 0
62 for pattern in file_patterns:
63 files = glob.glob (os.path.join (target_dir, pattern))
64 for file in files:
65 ref_file = os.path.join (ref_dir, os.path.basename (file))
66 if not os.path.isfile (ref_file):
67 sys.stderr.write ("Warning: %s: no such file.\nReference file for %s not found.\n" % (ref_file, file))
68 continue
69 f = open (file, 'r')
70 target_source = comment_re.split (f.read ())
71 f.close ()
72 if reduce (lambda x, y: x or y, ['-- SKELETON FILE --' in s for s in target_source]):
73 sys.stderr.write ("Skipping skeleton file %s\n" % file)
74 continue
75 g = open (ref_file, 'r')
76 ref_source = comment_re.split (g.read ())
77 target_source = snippet_split (target_source)
78 ref_source = snippet_split (ref_source)
79 if '' in target_source or '' in ref_source:
80 raise "AAAAARGH: unuseful empty string"
81 snippet_count = count_snippet (target_source)
82 if not snippet_count == count_snippet (ref_source):
83 update_exit_code (1)
84 sys.stderr.write ("Error: %s and %s have different snippet counts.\n\
85 Update translation by at least adding a @lilypond block where necessary, then rerun this script.\n" % (ref_file, file))
86 continue
87 total_snippet_count += snippet_count
88 c = 0
89 k = -1
90 for j in range (len (target_source)):
91 if target_source[j].startswith ('@lilypond'):
92 k = find_next_snippet (ref_source, k+1)
93 if j > 0 and (not target_source[j-1].startswith ('@c KEEP LY')) and target_source[j] != ref_source[k]:
94 target_source[j] = ref_source[k]
95 c += 1
96 changed_snippets_count += 1
97 f = open (file, 'w')
98 f.write (''.join (target_source))
99 sys.stderr.write ('%s: %d/%d snippets updated\n' % (file, c, snippet_count))
101 sys.stderr.write ('\nTotal: %d snippets, %d updated snippets.\n' % (total_snippet_count, changed_snippets_count))
102 sys.exit (exit_code)