Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/python
      2 #
      3 # Copyright (C) 2009 The Android Open Source Project
      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 Description:
     19    This script collects all framework Java sources from the current android
     20    source code and places them in a source folder suitable for the eclipse ADT
     21    plugin.
     22 
     23 See usage() below.
     24 
     25 Copyright (C) 2009 The Android Open Source Project
     26 Licensed under the Apache License, Version 2.0 (the "License").
     27 """
     28 
     29 import re
     30 import os
     31 import sys
     32 import getopt
     33 import shutil
     34 
     35 _RE_PKG = re.compile("^\s*package\s+([^\s;]+)\s*;.*")
     36 
     37 # Holds cmd-line arguments
     38 class Params(object):
     39     def __init__(self):
     40         self.DRY = False
     41         self.DIR = "frameworks libcore"
     42         self.SRC = None
     43         self.DST = None
     44         self.CNT_USED = 0
     45         self.CNT_NOPKG = 0
     46 
     47 
     48 # Prints a usage summary
     49 def usage(error=None):
     50     print """
     51  Description:
     52    This script collects all framework Java sources from the current android
     53    source code and places them in a source folder suitable for the eclipse ADT
     54    plugin.
     55 
     56  Usage:
     57    %s [-n] <android-git-repo root> <sdk/platforms/xyz/sources>
     58  
     59  The source and destination directories must already exist.
     60  Use -n for a dry-run.
     61 
     62 """ % sys.argv[0]
     63 
     64     if error:
     65         print >>sys.stderr, "Error:", error
     66 
     67 
     68 # Parse command line args, returns a Params instance or sys.exit(2) on error
     69 # after printing the error and the usage.
     70 def parseArgs(argv):
     71     p = Params()
     72     error = None
     73 
     74     try:
     75         opts, args = getopt.getopt(argv[1:],
     76                                    "ns:",
     77                                    [ "--dry", "--sourcedir=" ])
     78     except getopt.GetoptError, e:
     79         error = str(e)
     80 
     81     if error is None:
     82         for o, a in opts:
     83             if o in [ "-n", "--dry" ]:
     84                 p.DRY = True
     85             elif o in [ "-s", "--sourcedir" ]:
     86                 p.DIR = a
     87 
     88         if len(args) != 2:
     89             error = "Missing arguments: <source> <dest>"
     90         else:
     91             p.SRC = args[0]
     92             p.DST = args[1]
     93 
     94             if not os.path.isdir(p.SRC):
     95                 error = "%s is not a directory" % p.SRC
     96             elif not os.path.isdir(p.DST):
     97                 error = "%s is not a directory" % p.DST
     98 
     99     if error:
    100         usage(error)
    101         sys.exit(2)
    102 
    103     return p
    104 
    105 
    106 # Recursively parses the given directory and process java files found
    107 def parseSrcDir(p, srcdir):
    108     if not os.path.exists(srcdir):
    109         print >>sys.stderr, "Error: Skipping unknown directory", srcdir
    110         return
    111 
    112     for f in os.listdir(srcdir):
    113         fp = os.path.join(srcdir, f)
    114         if f.endswith(".java") and os.path.isfile(fp):
    115             pkg = checkJavaFile(fp)
    116             if pkg:
    117                 pkg = pkg.replace(".", os.path.sep)  # e.g. android.view => android/view
    118                 copy(p, fp, f, pkg)
    119                 p.CNT_USED += 1   # one more copied
    120             else:
    121                 p.CNT_NOPKG += 1  # this java file lacked a package declaration
    122         elif os.path.isdir(fp):
    123             parseSrcDir(p, fp)
    124 
    125 
    126 # Check a java file to find its package declaration, if any
    127 def checkJavaFile(path):
    128     print "Process", path
    129 
    130     try:
    131         f = None
    132         try:
    133             f = file(path)
    134             for l in f.readlines():
    135                 m = _RE_PKG.match(l)
    136                 if m:
    137                     return m.group(1)
    138         finally:
    139             if f: f.close()
    140     except Exception:
    141         pass
    142 
    143     return None
    144 
    145 
    146 # Create destination directory based on package name then copy the
    147 # source file in there
    148 def copy(p, fp, f, pkg):
    149     dstdir = os.path.join(p.DST, pkg)
    150     _mkdir(p, dstdir)
    151     _cp(p, fp, os.path.join(dstdir, f))
    152 
    153 
    154 def _mkdir(p, dir):
    155     if not os.path.isdir(dir):
    156         if p.DRY:
    157             print "mkdir", dir
    158         else:
    159             os.makedirs(dir)
    160 
    161 
    162 def _cp(p, src, dst):
    163     if p.DRY:
    164         print "cp", src, dst
    165     else:
    166         shutil.copyfile(src, dst)
    167 
    168 
    169 def main():
    170     p = parseArgs(sys.argv)
    171     for d in p.DIR.split():
    172         if d:
    173             parseSrcDir(p, os.path.join(p.SRC, d))
    174     print "%d java files copied" % p.CNT_USED
    175     if p.CNT_NOPKG: print "%d java files ignored (no package)" % p.CNT_NOPKG
    176     if p.DRY: print "This was in *DRY* mode. No copies done."
    177 
    178 
    179 if __name__ == "__main__":
    180     main()
    181