1# common python utility routines for the Bionic tool scripts
2
3import commands
4import logging
5import os
6import string
7import sys
8
9
10def panic(msg):
11    sys.stderr.write(os.path.basename(sys.argv[0]) + ": error: ")
12    sys.stderr.write(msg)
13    sys.exit(1)
14
15
16def get_kernel_headers_dir():
17    return os.path.join(get_android_root(), "external/kernel-headers")
18
19
20def get_kernel_headers_original_dir():
21    return os.path.join(get_kernel_headers_dir(), "original")
22
23
24def get_kernel_headers_modified_dir():
25    return os.path.join(get_kernel_headers_dir(), "modified")
26
27
28def get_kernel_dir():
29    return os.path.join(get_android_root(), "bionic/libc/kernel")
30
31
32def get_android_root():
33    if "ANDROID_BUILD_TOP" in os.environ:
34        return os.environ["ANDROID_BUILD_TOP"]
35    panic("Unable to find root of tree, did you forget to lunch a target?")
36
37
38class StringOutput:
39    def __init__(self):
40        self.line = ""
41
42    def write(self,msg):
43        self.line += msg
44        logging.debug("write '%s'" % msg)
45
46    def get(self):
47        return self.line
48
49
50def create_file_path(path):
51    dirs = []
52    while 1:
53        parent = os.path.dirname(path)
54        #print "parent: %s <- %s" % (parent, path)
55        if parent == "/" or parent == "":
56            break
57        dirs.append(parent)
58        path = parent
59
60    dirs.reverse()
61    for dir in dirs:
62        #print "dir %s" % dir
63        if os.path.isdir(dir):
64            continue
65        os.mkdir(dir)
66
67
68class BatchFileUpdater:
69    """a class used to edit several files at once"""
70    def __init__(self):
71        self.old_files = set()
72        self.new_files = set()
73        self.new_data  = {}
74
75    def readFile(self,path):
76        #path = os.path.realpath(path)
77        if os.path.exists(path):
78            self.old_files.add(path)
79
80    def readDir(self,path):
81        #path = os.path.realpath(path)
82        for root, dirs, files in os.walk(path):
83            for f in files:
84                dst = "%s/%s" % (root,f)
85                self.old_files.add(dst)
86
87    def editFile(self,dst,data):
88        """edit a destination file. if the file is not mapped from a source,
89           it will be added. return 0 if the file content wasn't changed,
90           1 if it was edited, or 2 if the file is new"""
91        #dst = os.path.realpath(dst)
92        result = 1
93        if os.path.exists(dst):
94            f = open(dst, "r")
95            olddata = f.read()
96            f.close()
97            if olddata == data:
98                self.old_files.remove(dst)
99                return 0
100        else:
101            result = 2
102
103        self.new_data[dst] = data
104        self.new_files.add(dst)
105        return result
106
107    def getChanges(self):
108        """determine changes, returns (adds, deletes, edits)"""
109        adds    = set()
110        edits   = set()
111        deletes = set()
112
113        for dst in self.new_files:
114            if not (dst in self.old_files):
115                adds.add(dst)
116            else:
117                edits.add(dst)
118
119        for dst in self.old_files:
120            if not dst in self.new_files:
121                deletes.add(dst)
122
123        return (adds, deletes, edits)
124
125    def _writeFile(self,dst):
126        if not os.path.exists(os.path.dirname(dst)):
127            create_file_path(dst)
128        f = open(dst, "w")
129        f.write(self.new_data[dst])
130        f.close()
131
132    def updateFiles(self):
133        adds, deletes, edits = self.getChanges()
134
135        for dst in sorted(adds):
136            self._writeFile(dst)
137
138        for dst in sorted(edits):
139            self._writeFile(dst)
140
141        for dst in sorted(deletes):
142            os.remove(dst)
143
144    def updateGitFiles(self):
145        adds, deletes, edits = self.getChanges()
146
147        if adds:
148            for dst in sorted(adds):
149                self._writeFile(dst)
150            commands.getoutput("git add " + " ".join(adds))
151
152        if deletes:
153            commands.getoutput("git rm " + " ".join(deletes))
154
155        if edits:
156            for dst in sorted(edits):
157                self._writeFile(dst)
158            commands.getoutput("git add " + " ".join(edits))
159