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        # Verify that the current directory is in the root.
35        # If not, then print an error.
36        cwd = os.getcwd()
37        root = os.environ["ANDROID_BUILD_TOP"]
38        if len(cwd) < len(root) or not root == cwd[:len(root)]:
39            panic("Not in android tree pointed at by ANDROID_BUILD_TOP (%s)\n" % root)
40        return os.environ["ANDROID_BUILD_TOP"]
41    panic("Unable to find root of tree, did you forget to lunch a target?\n")
42
43
44class StringOutput:
45    def __init__(self):
46        self.line = ""
47
48    def write(self,msg):
49        self.line += msg
50        logging.debug("write '%s'" % msg)
51
52    def get(self):
53        return self.line
54
55
56def create_file_path(path):
57    dirs = []
58    while 1:
59        parent = os.path.dirname(path)
60        #print "parent: %s <- %s" % (parent, path)
61        if parent == "/" or parent == "":
62            break
63        dirs.append(parent)
64        path = parent
65
66    dirs.reverse()
67    for dir in dirs:
68        #print "dir %s" % dir
69        if os.path.isdir(dir):
70            continue
71        os.mkdir(dir)
72
73
74class BatchFileUpdater:
75    """a class used to edit several files at once"""
76    def __init__(self):
77        self.old_files = set()
78        self.new_files = set()
79        self.new_data  = {}
80
81    def readFile(self,path):
82        #path = os.path.realpath(path)
83        if os.path.exists(path):
84            self.old_files.add(path)
85
86    def readDir(self,path):
87        #path = os.path.realpath(path)
88        for root, dirs, files in os.walk(path):
89            for f in files:
90                dst = "%s/%s" % (root,f)
91                self.old_files.add(dst)
92
93    def editFile(self,dst,data):
94        """edit a destination file. if the file is not mapped from a source,
95           it will be added. return 0 if the file content wasn't changed,
96           1 if it was edited, or 2 if the file is new"""
97        #dst = os.path.realpath(dst)
98        result = 1
99        if os.path.exists(dst):
100            f = open(dst, "r")
101            olddata = f.read()
102            f.close()
103            if olddata == data:
104                self.old_files.remove(dst)
105                return 0
106        else:
107            result = 2
108
109        self.new_data[dst] = data
110        self.new_files.add(dst)
111        return result
112
113    def getChanges(self):
114        """determine changes, returns (adds, deletes, edits)"""
115        adds    = set()
116        edits   = set()
117        deletes = set()
118
119        for dst in self.new_files:
120            if not (dst in self.old_files):
121                adds.add(dst)
122            else:
123                edits.add(dst)
124
125        for dst in self.old_files:
126            if not dst in self.new_files:
127                deletes.add(dst)
128
129        return (adds, deletes, edits)
130
131    def _writeFile(self,dst):
132        if not os.path.exists(os.path.dirname(dst)):
133            create_file_path(dst)
134        f = open(dst, "w")
135        f.write(self.new_data[dst])
136        f.close()
137
138    def updateFiles(self):
139        adds, deletes, edits = self.getChanges()
140
141        for dst in sorted(adds):
142            self._writeFile(dst)
143
144        for dst in sorted(edits):
145            self._writeFile(dst)
146
147        for dst in sorted(deletes):
148            os.remove(dst)
149
150    def updateGitFiles(self):
151        adds, deletes, edits = self.getChanges()
152
153        if adds:
154            for dst in sorted(adds):
155                self._writeFile(dst)
156            commands.getoutput("git add " + " ".join(adds))
157
158        if deletes:
159            commands.getoutput("git rm " + " ".join(deletes))
160
161        if edits:
162            for dst in sorted(edits):
163                self._writeFile(dst)
164            commands.getoutput("git add " + " ".join(edits))
165