11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# common python utility routines for the Bionic tool scripts
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectimport sys, os, commands, string, commands
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# basic debugging trace support
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# call D_setlevel to set the verbosity level
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# and D(), D2(), D3(), D4() to add traces
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectverbose = 0
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef panic(msg):
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.stderr.write( find_program_name() + ": error: " )
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.stderr.write( msg )
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    sys.exit(1)
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef D(msg):
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global verbose
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if verbose > 0:
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print msg
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef D2(msg):
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global verbose
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if verbose >= 2:
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print msg
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef D3(msg):
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global verbose
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if verbose >= 3:
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print msg
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef D4(msg):
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global verbose
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if verbose >= 4:
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print msg
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef D_setlevel(level):
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    global verbose
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    verbose = level
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#  other stuff
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef find_program_name():
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return os.path.basename(sys.argv[0])
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef find_program_dir():
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return os.path.dirname(sys.argv[0])
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef find_file_from_upwards(from_path,target_file):
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """find a file in the current directory or its parents. if 'from_path' is None,
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       seach from the current program's directory"""
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    path = from_path
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if path == None:
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        path = os.path.realpath(sys.argv[0])
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        path = os.path.dirname(path)
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        D("this script seems to be located in: %s" % path)
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    while 1:
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        D("probing "+path)
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if path == "":
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            file = target_file
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            file = path + "/" + target_file
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if os.path.isfile(file):
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D("found %s in %s" % (target_file, path))
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return file
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if path == "":
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        path = os.path.dirname(path)
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass StringOutput:
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self):
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line = ""
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def write(self,msg):
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line += msg
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        D2("write '%s'" % msg)
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def get(self):
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.line
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef create_file_path(path):
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    dirs = []
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    while 1:
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        parent = os.path.dirname(path)
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "parent: %s <- %s" % (parent, path)
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if parent == "/" or parent == "":
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        dirs.append(parent)
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        path = parent
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    dirs.reverse()
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for dir in dirs:
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "dir %s" % dir
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if os.path.isdir(dir):
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            continue
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        os.mkdir(dir)
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef walk_source_files(paths,callback,args,excludes=[]):
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """recursively walk a list of paths and files, only keeping the source files in directories"""
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for path in paths:
108fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if len(path) > 0 and path[0] == '@':
109fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # this is the name of another file, include it and parse it
110fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            path = path[1:]
111fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if os.path.exists(path):
112fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                for line in open(path):
113fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if len(line) > 0 and line[-1] == '\n':
114fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        line = line[:-1]
115fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    walk_source_files([line],callback,args,excludes)
116fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            continue
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not os.path.isdir(path):
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            callback(path,args)
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for root, dirs, files in os.walk(path):
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if len(excludes):
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    for d in dirs[:]:
124fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if os.path.join(root,d) in excludes:
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            dirs.remove(d)
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for f in files:
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    r, ext = os.path.splitext(f)
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if ext in [ ".h", ".c", ".cpp", ".S" ]:
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        callback( "%s/%s" % (root,f), args )
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef cleanup_dir(path):
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """create a directory if needed, and ensure that it is totally empty
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       by removing any existing content in it"""
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if not os.path.exists(path):
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        os.mkdir(path)
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for root, dirs, files in os.walk(path, topdown=False):
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if root.endswith("kernel_headers/"):
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # skip 'kernel_headers'
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                continue
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for name in files:
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                os.remove(os.path.join(root, name))
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for name in dirs:
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                os.rmdir(os.path.join(root, name))
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef update_file( path, newdata ):
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """update a file on disk, only if its content has changed"""
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if os.path.exists( path ):
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        try:
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            f = open( path, "r" )
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            olddata = f.read()
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            f.close()
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        except:
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D("update_file: cannot read existing file '%s'" % path)
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return 0
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if oldata == newdata:
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("update_file: no change to file '%s'" % path )
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return 0
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        update = 1
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        try:
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            create_file_path(path)
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        except:
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D("update_file: cannot create path to '%s'" % path)
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return 0
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    f = open( path, "w" )
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    f.write( newdata )
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    f.close()
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 1
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass BatchFileUpdater:
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to edit several files at once"""
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self):
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.old_files = set()
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.new_files = set()
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.new_data  = {}
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def readFile(self,path):
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #path = os.path.realpath(path)
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if os.path.exists(path):
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.old_files.add(path)
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def readDir(self,path):
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #path = os.path.realpath(path)
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for root, dirs, files in os.walk(path):
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for f in files:
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                dst = "%s/%s" % (root,f)
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.old_files.add(dst)
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def editFile(self,dst,data):
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """edit a destination file. if the file is not mapped from a source,
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           it will be added. return 0 if the file content wasn't changed,
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           1 if it was edited, or 2 if the file is new"""
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #dst = os.path.realpath(dst)
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = 1
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if os.path.exists(dst):
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            f = open(dst, "r")
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            olddata = f.read()
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            f.close()
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if olddata == data:
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.old_files.remove(dst)
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return 0
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result = 2
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.new_data[dst] = data
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.new_files.add(dst)
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def getChanges(self):
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """determine changes, returns (adds, deletes, edits)"""
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        adds    = set()
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        edits   = set()
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        deletes = set()
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for dst in self.new_files:
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if not (dst in self.old_files):
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                adds.add(dst)
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                edits.add(dst)
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for dst in self.old_files:
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if not dst in self.new_files:
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                deletes.add(dst)
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return (adds, deletes, edits)
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
233c95eb57405d3d2f0e6cfab313aa74b1bad280452Elliott Hughes    def _writeFile(self,dst):
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not os.path.exists(os.path.dirname(dst)):
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            create_file_path(dst)
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        f = open(dst, "w")
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        f.write(self.new_data[dst])
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        f.close()
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def updateFiles(self):
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        adds, deletes, edits = self.getChanges()
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for dst in sorted(adds):
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self._writeFile(dst)
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for dst in sorted(edits):
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self._writeFile(dst)
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for dst in sorted(deletes):
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            os.remove(dst)
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
252fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    def updateGitFiles(self):
253fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        adds, deletes, edits = self.getChanges()
254fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
255fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if adds:
256fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            for dst in sorted(adds):
257fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                self._writeFile(dst)
258fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            commands.getoutput("git add " + " ".join(adds))
259fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
260fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if deletes:
261fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            commands.getoutput("git rm " + " ".join(deletes))
262fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
263fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if edits:
264fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            for dst in sorted(edits):
265fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                self._writeFile(dst)
266fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            commands.getoutput("git add " + " ".join(edits))
267