• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
7GRIT tools.
8"""
9
10import os
11import sys
12if __name__ == '__main__':
13  sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
14
15import getopt
16
17from grit import util
18
19import 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.
23def ToolFactoryBuild():
24  import grit.tool.build
25  return grit.tool.build.RcBuilder()
26
27def ToolFactoryBuildInfo():
28  import grit.tool.buildinfo
29  return grit.tool.buildinfo.DetermineBuildInfo()
30
31def ToolFactoryCount():
32  import grit.tool.count
33  return grit.tool.count.CountMessage()
34
35def ToolFactoryDiffStructures():
36  import grit.tool.diff_structures
37  return grit.tool.diff_structures.DiffStructures()
38
39def ToolFactoryMenuTranslationsFromParts():
40  import grit.tool.menu_from_parts
41  return grit.tool.menu_from_parts.MenuTranslationsFromParts()
42
43def ToolFactoryNewGrd():
44  import grit.tool.newgrd
45  return grit.tool.newgrd.NewGrd()
46
47def ToolFactoryResizeDialog():
48  import grit.tool.resize
49  return grit.tool.resize.ResizeDialog()
50
51def ToolFactoryRc2Grd():
52  import grit.tool.rc2grd
53  return grit.tool.rc2grd.Rc2Grd()
54
55def ToolFactoryTest():
56  import grit.tool.test
57  return grit.tool.test.TestTool()
58
59def ToolFactoryTranslationToTc():
60  import grit.tool.transl2tc
61  return grit.tool.transl2tc.TranslationToTc()
62
63def ToolFactoryUnit():
64  import grit.tool.unit
65  return grit.tool.unit.UnitTestTool()
66
67def ToolFactoryXmb():
68  import grit.tool.xmb
69  return grit.tool.xmb.OutputXmb()
70
71def 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
108def 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
122Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
123
124Global 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
142Tools:
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
151class 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
197def _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
207def 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
271if __name__ == '__main__':
272  sys.exit(Main(sys.argv[1:]))
273