tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

depswriter.py (6286B)


      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2009 The Closure Library Authors. All Rights Reserved.
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS-IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 
     18 """Generates out a Closure deps.js file given a list of JavaScript sources.
     19 
     20 Paths can be specified as arguments or (more commonly) specifying trees
     21 with the flags (call with --help for descriptions).
     22 
     23 Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
     24 """
     25 
     26 import logging
     27 import optparse
     28 import os
     29 import posixpath
     30 import shlex
     31 import sys
     32 
     33 import source
     34 import treescan
     35 
     36 
     37 __author__ = 'nnaze@google.com (Nathan Naze)'
     38 
     39 
     40 def MakeDepsFile(source_map):
     41  """Make a generated deps file.
     42 
     43  Args:
     44    source_map: A dict map of the source path to source.Source object.
     45 
     46  Returns:
     47    str, A generated deps file source.
     48  """
     49 
     50  # Write in path alphabetical order
     51  paths = sorted(source_map.keys())
     52 
     53  lines = []
     54 
     55  for path in paths:
     56    js_source = source_map[path]
     57 
     58    # We don't need to add entries that don't provide anything.
     59    if js_source.provides:
     60      lines.append(_GetDepsLine(path, js_source))
     61 
     62  return ''.join(lines)
     63 
     64 
     65 def _GetDepsLine(path, js_source):
     66  """Get a deps.js file string for a source."""
     67 
     68  provides = sorted(js_source.provides)
     69  requires = sorted(js_source.requires)
     70  module = 'true' if js_source.is_goog_module else 'false'
     71 
     72  return 'goog.addDependency(\'%s\', %s, %s, %s);\n' % (
     73      path, provides, requires, module)
     74 
     75 
     76 def _GetOptionsParser():
     77  """Get the options parser."""
     78 
     79  parser = optparse.OptionParser(__doc__)
     80 
     81  parser.add_option('--output_file',
     82                    dest='output_file',
     83                    action='store',
     84                    help=('If specified, write output to this path instead of '
     85                          'writing to standard output.'))
     86  parser.add_option('--root',
     87                    dest='roots',
     88                    default=[],
     89                    action='append',
     90                    help='A root directory to scan for JS source files. '
     91                    'Paths of JS files in generated deps file will be '
     92                    'relative to this path.  This flag may be specified '
     93                    'multiple times.')
     94  parser.add_option('--root_with_prefix',
     95                    dest='roots_with_prefix',
     96                    default=[],
     97                    action='append',
     98                    help='A root directory to scan for JS source files, plus '
     99                    'a prefix (if either contains a space, surround with '
    100                    'quotes).  Paths in generated deps file will be relative '
    101                    'to the root, but preceded by the prefix.  This flag '
    102                    'may be specified multiple times.')
    103  parser.add_option('--path_with_depspath',
    104                    dest='paths_with_depspath',
    105                    default=[],
    106                    action='append',
    107                    help='A path to a source file and an alternate path to '
    108                    'the file in the generated deps file (if either contains '
    109                    'a space, surround with whitespace). This flag may be '
    110                    'specified multiple times.')
    111  return parser
    112 
    113 
    114 def _NormalizePathSeparators(path):
    115  """Replaces OS-specific path separators with POSIX-style slashes.
    116 
    117  Args:
    118    path: str, A file path.
    119 
    120  Returns:
    121    str, The path with any OS-specific path separators (such as backslash on
    122      Windows) replaced with URL-compatible forward slashes. A no-op on systems
    123      that use POSIX paths.
    124  """
    125  return path.replace(os.sep, posixpath.sep)
    126 
    127 
    128 def _GetRelativePathToSourceDict(root, prefix=''):
    129  """Scans a top root directory for .js sources.
    130 
    131  Args:
    132    root: str, Root directory.
    133    prefix: str, Prefix for returned paths.
    134 
    135  Returns:
    136    dict, A map of relative paths (with prefix, if given), to source.Source
    137      objects.
    138  """
    139  # Remember and restore the cwd when we're done. We work from the root so
    140  # that paths are relative from the root.
    141  start_wd = os.getcwd()
    142  os.chdir(root)
    143 
    144  path_to_source = {}
    145  for path in treescan.ScanTreeForJsFiles('.'):
    146    prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
    147    path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
    148 
    149  os.chdir(start_wd)
    150 
    151  return path_to_source
    152 
    153 
    154 def _GetPair(s):
    155  """Return a string as a shell-parsed tuple.  Two values expected."""
    156  try:
    157    # shlex uses '\' as an escape character, so they must be escaped.
    158    s = s.replace('\\', '\\\\')
    159    first, second = shlex.split(s)
    160    return (first, second)
    161  except:
    162    raise Exception('Unable to parse input line as a pair: %s' % s)
    163 
    164 
    165 def main():
    166  """CLI frontend to MakeDepsFile."""
    167  logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
    168                      level=logging.INFO)
    169  options, args = _GetOptionsParser().parse_args()
    170 
    171  path_to_source = {}
    172 
    173  # Roots without prefixes
    174  for root in options.roots:
    175    path_to_source.update(_GetRelativePathToSourceDict(root))
    176 
    177  # Roots with prefixes
    178  for root_and_prefix in options.roots_with_prefix:
    179    root, prefix = _GetPair(root_and_prefix)
    180    path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
    181 
    182  # Source paths
    183  for path in args:
    184    path_to_source[path] = source.Source(source.GetFileContents(path))
    185 
    186  # Source paths with alternate deps paths
    187  for path_with_depspath in options.paths_with_depspath:
    188    srcpath, depspath = _GetPair(path_with_depspath)
    189    path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
    190 
    191  # Make our output pipe.
    192  if options.output_file:
    193    out = open(options.output_file, 'w')
    194  else:
    195    out = sys.stdout
    196 
    197  out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
    198  out.write('// Please do not edit.\n')
    199 
    200  out.write(MakeDepsFile(path_to_source))
    201 
    202 
    203 if __name__ == '__main__':
    204  main()