OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Command processor for GRIT. This is the script you invoke to run the various | |
7 GRIT tools. | |
8 """ | |
9 | |
10 import os | |
11 import sys | |
12 if __name__ == '__main__': | |
13 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) | |
14 | |
15 import getopt | |
16 | |
17 from grit import util | |
18 | |
19 import grit.extern.FP | |
20 | |
21 # Tool info factories; these import only within each factory to avoid | |
22 # importing most of the GRIT code until required. | |
23 def ToolFactoryBuild(): | |
24 import grit.tool.build | |
25 return grit.tool.build.RcBuilder() | |
26 | |
27 def ToolFactoryBuildInfo(): | |
28 import grit.tool.buildinfo | |
29 return grit.tool.buildinfo.DetermineBuildInfo() | |
30 | |
31 def ToolFactoryCount(): | |
32 import grit.tool.count | |
33 return grit.tool.count.CountMessage() | |
34 | |
35 def ToolFactoryDiffStructures(): | |
36 import grit.tool.diff_structures | |
37 return grit.tool.diff_structures.DiffStructures() | |
38 | |
39 def ToolFactoryMenuTranslationsFromParts(): | |
40 import grit.tool.menu_from_parts | |
41 return grit.tool.menu_from_parts.MenuTranslationsFromParts() | |
42 | |
43 def ToolFactoryNewGrd(): | |
44 import grit.tool.newgrd | |
45 return grit.tool.newgrd.NewGrd() | |
46 | |
47 def ToolFactoryResizeDialog(): | |
48 import grit.tool.resize | |
49 return grit.tool.resize.ResizeDialog() | |
50 | |
51 def ToolFactoryRc2Grd(): | |
52 import grit.tool.rc2grd | |
53 return grit.tool.rc2grd.Rc2Grd() | |
54 | |
55 def ToolFactoryTest(): | |
56 import grit.tool.test | |
57 return grit.tool.test.TestTool() | |
58 | |
59 def ToolFactoryTranslationToTc(): | |
60 import grit.tool.transl2tc | |
61 return grit.tool.transl2tc.TranslationToTc() | |
62 | |
63 def ToolFactoryUnit(): | |
64 import grit.tool.unit | |
65 return grit.tool.unit.UnitTestTool() | |
66 | |
67 def ToolFactoryXmb(): | |
68 import grit.tool.xmb | |
69 return grit.tool.xmb.OutputXmb() | |
70 | |
71 def ToolAndroid2Grd(): | |
72 import grit.tool.android2grd | |
73 return grit.tool.android2grd.Android2Grd() | |
74 | |
75 # Keys for the following map | |
76 _FACTORY = 1 | |
77 _REQUIRES_INPUT = 2 | |
78 _HIDDEN = 3 # optional key - presence indicates tool is hidden | |
79 | |
80 # Maps tool names to the tool's module. Done as a list of (key, value) tuples | |
81 # instead of a map to preserve ordering. | |
82 _TOOLS = [ | |
83 ['build', { _FACTORY : ToolFactoryBuild, _REQUIRES_INPUT : True }], | |
84 ['buildinfo', { _FACTORY : ToolFactoryBuildInfo, _REQUIRES_INPUT : True }], | |
85 ['count', { _FACTORY : ToolFactoryCount, _REQUIRES_INPUT : True }], | |
86 ['menufromparts', { | |
87 _FACTORY: ToolFactoryMenuTranslationsFromParts, | |
88 _REQUIRES_INPUT : True, _HIDDEN : True }], | |
89 ['newgrd', { _FACTORY : ToolFactoryNewGrd, _REQUIRES_INPUT : False }], | |
90 ['rc2grd', { _FACTORY : ToolFactoryRc2Grd, _REQUIRES_INPUT : False }], | |
91 ['resize', { | |
92 _FACTORY : ToolFactoryResizeDialog, _REQUIRES_INPUT : True }], | |
93 ['sdiff', { _FACTORY : ToolFactoryDiffStructures, | |
94 _REQUIRES_INPUT : False }], | |
95 ['test', { | |
96 _FACTORY: ToolFactoryTest, _REQUIRES_INPUT : True, | |
97 _HIDDEN : True }], | |
98 ['transl2tc', { _FACTORY : ToolFactoryTranslationToTc, | |
99 _REQUIRES_INPUT : False }], | |
100 ['unit', { _FACTORY : ToolFactoryUnit, _REQUIRES_INPUT : False }], | |
101 ['xmb', { _FACTORY : ToolFactoryXmb, _REQUIRES_INPUT : True }], | |
102 ['android2grd', { | |
103 _FACTORY: ToolAndroid2Grd, | |
104 _REQUIRES_INPUT : False }], | |
105 ] | |
106 | |
107 | |
108 def PrintUsage(): | |
109 tool_list = '' | |
110 for (tool, info) in _TOOLS: | |
111 if not _HIDDEN in info.keys(): | |
112 tool_list += ' %-12s %s\n' % (tool, info[_FACTORY]().ShortDescription()
) | |
113 | |
114 # TODO(joi) Put these back into the usage when appropriate: | |
115 # | |
116 # -d Work disconnected. This causes GRIT not to attempt connections with | |
117 # e.g. Perforce. | |
118 # | |
119 # -c Use the specified Perforce CLIENT when talking to Perforce. | |
120 print """GRIT - the Google Resource and Internationalization Tool | |
121 | |
122 Usage: grit [GLOBALOPTIONS] TOOL [args to tool] | |
123 | |
124 Global options: | |
125 | |
126 -i INPUT Specifies the INPUT file to use (a .grd file). If this is not | |
127 specified, GRIT will look for the environment variable GRIT_INPUT. | |
128 If it is not present either, GRIT will try to find an input file | |
129 named 'resource.grd' in the current working directory. | |
130 | |
131 -h MODULE Causes GRIT to use MODULE.UnsignedFingerPrint instead of | |
132 grit.extern.FP.UnsignedFingerprint. MODULE must be | |
133 available somewhere in the PYTHONPATH search path. | |
134 | |
135 -v Print more verbose runtime information. | |
136 | |
137 -x Print extremely verbose runtime information. Implies -v | |
138 | |
139 -p FNAME Specifies that GRIT should profile its execution and output the | |
140 results to the file FNAME. | |
141 | |
142 Tools: | |
143 | |
144 TOOL can be one of the following: | |
145 %s | |
146 For more information on how to use a particular tool, and the specific | |
147 arguments you can send to that tool, execute 'grit help TOOL' | |
148 """ % (tool_list) | |
149 | |
150 | |
151 class Options(object): | |
152 """Option storage and parsing.""" | |
153 | |
154 def __init__(self): | |
155 self.disconnected = False | |
156 self.client = '' | |
157 self.hash = None | |
158 self.input = None | |
159 self.verbose = False | |
160 self.extra_verbose = False | |
161 self.output_stream = sys.stdout | |
162 self.profile_dest = None | |
163 self.psyco = False | |
164 | |
165 def ReadOptions(self, args): | |
166 """Reads options from the start of args and returns the remainder.""" | |
167 (opts, args) = getopt.getopt(args, 'g:qdvxc:i:p:h:', ('psyco',)) | |
168 for (key, val) in opts: | |
169 if key == '-d': self.disconnected = True | |
170 elif key == '-c': self.client = val | |
171 elif key == '-h': self.hash = val | |
172 elif key == '-i': self.input = val | |
173 elif key == '-v': | |
174 self.verbose = True | |
175 util.verbose = True | |
176 elif key == '-x': | |
177 self.verbose = True | |
178 util.verbose = True | |
179 self.extra_verbose = True | |
180 util.extra_verbose = True | |
181 elif key == '-p': self.profile_dest = val | |
182 elif key == '--psyco': self.psyco = True | |
183 | |
184 if not self.input: | |
185 if 'GRIT_INPUT' in os.environ: | |
186 self.input = os.environ['GRIT_INPUT'] | |
187 else: | |
188 self.input = 'resource.grd' | |
189 | |
190 return args | |
191 | |
192 def __repr__(self): | |
193 return '(disconnected: %d, verbose: %d, client: %s, input: %s)' % ( | |
194 self.disconnected, self.verbose, self.client, self.input) | |
195 | |
196 | |
197 def _GetToolInfo(tool): | |
198 """Returns the info map for the tool named 'tool' or None if there is no | |
199 such tool.""" | |
200 matches = [t for t in _TOOLS if t[0] == tool] | |
201 if not matches: | |
202 return None | |
203 else: | |
204 return matches[0][1] | |
205 | |
206 | |
207 def Main(args): | |
208 """Parses arguments and does the appropriate thing.""" | |
209 util.ChangeStdoutEncoding() | |
210 | |
211 if sys.version_info < (2, 6): | |
212 print "GRIT requires Python 2.6 or later." | |
213 return 2 | |
214 elif not args or (len(args) == 1 and args[0] == 'help'): | |
215 PrintUsage() | |
216 return 0 | |
217 elif len(args) == 2 and args[0] == 'help': | |
218 tool = args[1].lower() | |
219 if not _GetToolInfo(tool): | |
220 print "No such tool. Try running 'grit help' for a list of tools." | |
221 return 2 | |
222 | |
223 print ("Help for 'grit %s' (for general help, run 'grit help'):\n" | |
224 % (tool)) | |
225 print _GetToolInfo(tool)[_FACTORY]().__doc__ | |
226 return 0 | |
227 else: | |
228 options = Options() | |
229 args = options.ReadOptions(args) # args may be shorter after this | |
230 if not args: | |
231 print "No tool provided. Try running 'grit help' for a list of tools." | |
232 return 2 | |
233 tool = args[0] | |
234 if not _GetToolInfo(tool): | |
235 print "No such tool. Try running 'grit help' for a list of tools." | |
236 return 2 | |
237 | |
238 try: | |
239 if _GetToolInfo(tool)[_REQUIRES_INPUT]: | |
240 os.stat(options.input) | |
241 except OSError: | |
242 print ('Input file %s not found.\n' | |
243 'To specify a different input file:\n' | |
244 ' 1. Use the GRIT_INPUT environment variable.\n' | |
245 ' 2. Use the -i command-line option. This overrides ' | |
246 'GRIT_INPUT.\n' | |
247 ' 3. Specify neither GRIT_INPUT or -i and GRIT will try to load ' | |
248 "'resource.grd'\n" | |
249 ' from the current directory.' % options.input) | |
250 return 2 | |
251 | |
252 if options.psyco: | |
253 # Psyco is a specializing JIT for Python. Early tests indicate that it | |
254 # could speed up GRIT (at the expense of more memory) for large GRIT | |
255 # compilations. See http://psyco.sourceforge.net/ | |
256 import psyco | |
257 psyco.profile() | |
258 | |
259 if options.hash: | |
260 grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash) | |
261 | |
262 toolobject = _GetToolInfo(tool)[_FACTORY]() | |
263 if options.profile_dest: | |
264 import hotshot | |
265 prof = hotshot.Profile(options.profile_dest) | |
266 prof.runcall(toolobject.Run, options, args[1:]) | |
267 else: | |
268 toolobject.Run(options, args[1:]) | |
269 | |
270 | |
271 if __name__ == '__main__': | |
272 sys.exit(Main(sys.argv[1:])) | |
OLD | NEW |