1655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng# common python utility routines for the Bionic tool scripts
2655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
3655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengimport commands
4655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengimport logging
5655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengimport os
6655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengimport string
7655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengimport sys
8655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
9655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
10655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef panic(msg):
11655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    sys.stderr.write(os.path.basename(sys.argv[0]) + ": error: ")
12655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    sys.stderr.write(msg)
13655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    sys.exit(1)
14655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
15655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
16655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef get_kernel_headers_dir():
17655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    return os.path.join(get_android_root(), "external/kernel-headers")
18655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
19655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
20655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef get_kernel_headers_original_dir():
21655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    return os.path.join(get_kernel_headers_dir(), "original")
22655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
23655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
24655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef get_kernel_headers_modified_dir():
25655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    return os.path.join(get_kernel_headers_dir(), "modified")
26655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
27655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
28655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef get_kernel_dir():
29655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    return os.path.join(get_android_root(), "bionic/libc/kernel")
30655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
31655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
32655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef get_android_root():
33655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    if "ANDROID_BUILD_TOP" in os.environ:
34655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        # Verify that the current directory is in the root.
35655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        # If not, then print an error.
36655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        cwd = os.getcwd()
37655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        root = os.environ["ANDROID_BUILD_TOP"]
38655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        if len(cwd) < len(root) or not root == cwd[:len(root)]:
39655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng            panic("Not in android tree pointed at by ANDROID_BUILD_TOP (%s)\n" % root)
40d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        return os.environ["ANDROID_BUILD_TOP"]
41d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    panic("Unable to find root of tree, did you forget to lunch a target?\n")
42d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
43d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
44655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengclass StringOutput:
45655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    def __init__(self):
46655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        self.line = ""
47d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
48d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    def write(self,msg):
49655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        self.line += msg
50655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        logging.debug("write '%s'" % msg)
51655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
52d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    def get(self):
53d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        return self.line
54d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
55655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
56655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Chengdef create_file_path(path):
57655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    dirs = []
58d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    while 1:
59d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        parent = os.path.dirname(path)
60d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        #print "parent: %s <- %s" % (parent, path)
61d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        if parent == "/" or parent == "":
62d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao            break
63d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        dirs.append(parent)
64655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        path = parent
65655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
6605d08e9716b5974d6ed08973f44930804890b902Christopher Ferris    dirs.reverse()
6705d08e9716b5974d6ed08973f44930804890b902Christopher Ferris    for dir in dirs:
6805d08e9716b5974d6ed08973f44930804890b902Christopher Ferris        #print "dir %s" % dir
69655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        if os.path.isdir(dir):
70655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng            continue
71655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng        os.mkdir(dir)
72d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
73d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao
74d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass BatchFileUpdater:
75d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    """a class used to edit several files at once"""
76d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao    def __init__(self):
77d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        self.old_files = set()
78d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        self.new_files = set()
79d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao        self.new_data  = {}
80655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng
81655a7c081f83b8351ed5f11a6c6accd9458293a8Ben Cheng    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