-
Notifications
You must be signed in to change notification settings - Fork 536
/
left_to_do.groovy
executable file
·148 lines (123 loc) · 4.65 KB
/
left_to_do.groovy
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#! /usr/bin/env groovy
/**
* Script that recursively compares everything within {hidden} macros in a
* user guide translation with another gdoc source directory. By default,
* the translation is compared against the reference 'en' docs.
*/
if (!args || args.size() > 3) {
println """\
USAGE
left_to_do LANG [LANG] [-nc]
where
LANG = a language code, e.g. 'en' or 'pt_BR'
-nc means: copy the new file if the target LANG file does not exist
Compares the contents of the {hidden} blocks in the user guide for the first language
against the entire contents of the second language. By default, the second language
is 'en', i.e. the reference user guide (which has no {hidden} blocks).\
""".stripIndent()
System.exit 1
}
// Create a temporary directory to dump the extracted {hidden} contents to.
def tmpDocDir = new File("tmp")
if (tmpDocDir.exists()) {
println "Removing the old temporary output directory"
tmpDocDir.deleteDir()
}
tmpDocDir.mkdirs()
// Recursively copy the {hidden} blocks from the source language to the temporary
// directory, ensuring the resulting files have the same relative paths and names
// as the originals.
def srcDir = new File("src", args[0])
if (!srcDir.exists()) {
println "No source directory for language '${args[0]}'"
System.exit 2
}
def refDir = new File("src", args.size() >= 2 ? args[1] : 'en')
def isNc = (args.size() >= 3 && args[2]=='-nc') ? true :false
def ant = new AntBuilder()
srcDir.eachFileRecurse { f ->
if (f.directory) {
// Recreate this directory in the temporary output folder.
new File(tmpDocDir, relativePath(srcDir, f)).mkdir()
}
else {
// Read the source file, create a target file with the same
// name and relative location, and write out the contents of
// {hidden} blocks to that target file. Note the target file
// will include the {hidden} macros.
def relPathStr = relativePath(srcDir, f)
def targetFile = new File(refDir, relPathStr)
if (isNc && !targetFile.exists()) {
if (!targetFile.parentFile.exists()) {
targetFile.parentFile.mkdirs()
}
ant.copy(file:f,tofile:targetFile)
}
targetFile = new File(tmpDocDir, relPathStr)
writeHiddenToFile f.text, targetFile
}
}
// Now recursively diff the generated files against the reference directory.
generateDiff refDir, tmpDocDir
/// End of script execution ///
def relativePath(File baseDir, File file) {
def relativePath = file.absolutePath - baseDir.absolutePath
if (relativePath[0] == File.separator) relativePath = relativePath[1..-1]
return relativePath
}
def writeHiddenToFile(String text, File target) {
target.withWriter { w ->
def marker = 0
while (marker != -1) {
def startHidden = findNextMacro(text, marker, "hidden")
def startCode = findNextMacro(text, marker, "code")
def start
def macro
def writeMacro = false
if (startHidden != -1 && (startHidden < startCode || startCode == -1)) {
macro = "hidden"
start = startHidden
}
else {
macro = "code"
start = startCode
writeMacro = true
}
def end = start == -1 ? -1 : findNextMacro(text, start + 1, macro)
if (end != -1) {
if (!writeMacro) {
start = start + macroLength(macro)
}
else {
end = end + macroLength(macro)
}
w << text.substring(start, end)
if (writeMacro) w << '\n'
marker = end
if (!writeMacro) marker++
}
else {
marker = -1
}
}
}
}
def generateDiff(File refDir, File targetDir) {
def pb = new ProcessBuilder(["diff", "--unified", "--recursive", refDir.absolutePath, targetDir.absolutePath])
pb.redirectErrorStream true
def process = pb.start()
process.consumeProcessOutputStream System.out
process.waitFor()
}
def findNextMacro(String text, start, macro) {
// This matches {macro} and {macro:...} unless the opening
// brace is escaped with a backslash. The first parentheses
// correspond to a negative lookbehind to exclude '\{'.
def m = text =~ /(?<!\\)\{${macro}(?::[^\}]+)?\}/
m.region start, text.size()
return m.find() ? m.start() : -1
}
def macroLength(macro) {
// Length of macro name + 2 for the '{' and '}'
return macro.size() + 2
}