Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/python
      2 #
      3 # Copyright (C) 2009 Google Inc. All rights reserved.
      4 # 
      5 # Redistribution and use in source and binary forms, with or without
      6 # modification, are permitted provided that the following conditions are
      7 # met:
      8 # 
      9 #     * Redistributions of source code must retain the above copyright
     10 # notice, this list of conditions and the following disclaimer.
     11 #     * Redistributions in binary form must reproduce the above
     12 # copyright notice, this list of conditions and the following disclaimer
     13 # in the documentation and/or other materials provided with the
     14 # distribution.
     15 #     * Neither the name of Google Inc. nor the names of its
     16 # contributors may be used to endorse or promote products derived from
     17 # this software without specific prior written permission.
     18 # 
     19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 #
     31 # action_csspropertynames.py is a harness script to connect actions sections of
     32 # gyp-based builds to makeprop.pl.
     33 #
     34 # usage: action_makenames.py OUTPUTS -- INPUTS
     35 #
     36 # Exactly two outputs must be specified: a path to each of CSSPropertyNames.cpp
     37 # and CSSPropertyNames.h.
     38 #
     39 # Multiple inputs may be specified. One input must have a basename of
     40 # makeprop.pl; this is taken as the path to makeprop.pl. All other inputs are
     41 # paths to .in files that are used as input to makeprop.pl; at least one,
     42 # CSSPropertyNames.in, is required.
     43 
     44 
     45 import os
     46 import posixpath
     47 import shutil
     48 import subprocess
     49 import sys
     50 
     51 
     52 def SplitArgsIntoSections(args):
     53     sections = []
     54     while len(args) > 0:
     55         if not '--' in args:
     56             # If there is no '--' left, everything remaining is an entire section.
     57             dashes = len(args)
     58         else:
     59             dashes = args.index('--')
     60 
     61         sections.append(args[:dashes])
     62 
     63         # Next time through the loop, look at everything after this '--'.
     64         if dashes + 1 == len(args):
     65             # If the '--' is at the end of the list, we won't come back through the
     66             # loop again. Add an empty section now corresponding to the nothingness
     67             # following the final '--'.
     68             args = []
     69             sections.append(args)
     70         else:
     71             args = args[dashes + 1:]
     72 
     73     return sections
     74 
     75 
     76 def main(args):
     77     (outputs, inputs) = SplitArgsIntoSections(args[1:])
     78 
     79     # Make all output pathnames absolute so that they can be accessed after
     80     # changing directory.
     81     for index in xrange(0, len(outputs)):
     82         outputs[index] = os.path.abspath(outputs[index])
     83 
     84     outputDir = os.path.dirname(outputs[0])
     85 
     86     # Look at the inputs and figure out which one is makeprop.pl and which are
     87     # inputs to that script.
     88     makepropInput = None
     89     inFiles = []
     90     for input in inputs:
     91         # Make input pathnames absolute so they can be accessed after changing
     92         # directory. On Windows, convert \ to / for inputs to the perl script to
     93         # work around the intermix of activepython + cygwin perl.
     94         inputAbs = os.path.abspath(input)
     95         inputAbsPosix = inputAbs.replace(os.path.sep, posixpath.sep)
     96         inputBasename = os.path.basename(input)
     97         if inputBasename == 'makeprop.pl':
     98             assert makepropInput == None
     99             makepropInput = inputAbs
    100         elif inputBasename.endswith('.in'):
    101             inFiles.append(inputAbsPosix)
    102         else:
    103             assert False
    104 
    105     assert makepropInput != None
    106     assert len(inFiles) >= 1
    107 
    108     # Change to the output directory because makeprop.pl puts output in its
    109     # working directory.
    110     os.chdir(outputDir)
    111 
    112     # Merge all inFiles into a single file whose name will be the same as the
    113     # first listed inFile, but in the output directory.
    114     mergedPath = os.path.basename(inFiles[0])
    115     merged = open(mergedPath, 'wb')    # 'wb' to get \n only on windows
    116 
    117     # Make sure there aren't any duplicate lines in the in files.
    118     lineDict = {}
    119     for inFilePath in inFiles:
    120         inFile = open(inFilePath)
    121         for line in inFile:
    122             line = line.rstrip()
    123             if line.startswith('#'):
    124                 line = ''
    125             if line == '':
    126                 continue
    127             if line in lineDict:
    128                 raise KeyError, 'Duplicate value %s' % line
    129             lineDict[line] = True
    130             print >>merged, line
    131         inFile.close()
    132 
    133     merged.close()
    134 
    135     # Build up the command.
    136     command = ['perl', makepropInput]
    137 
    138     # Do it. checkCall is new in 2.5, so simulate its behavior with call and
    139     # assert.
    140     returnCode = subprocess.call(command)
    141     assert returnCode == 0
    142 
    143     # Don't leave behind the merged file or the .gperf file created by
    144     # makeprop.
    145     (root, ext) = os.path.splitext(mergedPath)
    146     gperfPath = root + '.gperf'
    147     os.unlink(gperfPath)
    148     os.unlink(mergedPath)
    149 
    150     # Go through the outputs. Any output that belongs in a different directory
    151     # is moved. Do a copy and delete instead of rename for maximum portability.
    152     # Note that all paths used in this section are still absolute.
    153     for output in outputs:
    154         thisOutputDir = os.path.dirname(output)
    155         if thisOutputDir != outputDir:
    156             outputBasename = os.path.basename(output)
    157             src = os.path.join(outputDir, outputBasename)
    158             dst = os.path.join(thisOutputDir, outputBasename)
    159             shutil.copyfile(src, dst)
    160             os.unlink(src)
    161 
    162     return returnCode
    163 
    164 
    165 if __name__ == '__main__':
    166     sys.exit(main(sys.argv))
    167