• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# common python utility routines for the Bionic tool scripts
2
3import sys, os, commands, string, commands
4
5# basic debugging trace support
6# call D_setlevel to set the verbosity level
7# and D(), D2(), D3(), D4() to add traces
8#
9verbose = 0
10
11def panic(msg):
12    sys.stderr.write( find_program_name() + ": error: " )
13    sys.stderr.write( msg )
14    sys.exit(1)
15
16def D(msg):
17    global verbose
18    if verbose > 0:
19        print msg
20
21def D2(msg):
22    global verbose
23    if verbose >= 2:
24        print msg
25
26def D3(msg):
27    global verbose
28    if verbose >= 3:
29        print msg
30
31def D4(msg):
32    global verbose
33    if verbose >= 4:
34        print msg
35
36def D_setlevel(level):
37    global verbose
38    verbose = level
39
40
41#  other stuff
42#
43#
44def find_program_name():
45    return os.path.basename(sys.argv[0])
46
47def find_program_dir():
48    return os.path.dirname(sys.argv[0])
49
50def find_file_from_upwards(from_path,target_file):
51    """find a file in the current directory or its parents. if 'from_path' is None,
52       seach from the current program's directory"""
53    path = from_path
54    if path == None:
55        path = os.path.realpath(sys.argv[0])
56        path = os.path.dirname(path)
57        D("this script seems to be located in: %s" % path)
58
59    while 1:
60        D("probing "+path)
61        if path == "":
62            file = target_file
63        else:
64            file = path + "/" + target_file
65
66        if os.path.isfile(file):
67            D("found %s in %s" % (target_file, path))
68            return file
69
70        if path == "":
71            return None
72
73        path = os.path.dirname(path)
74
75
76class StringOutput:
77    def __init__(self):
78        self.line = ""
79
80    def write(self,msg):
81        self.line += msg
82        D2("write '%s'" % msg)
83
84    def get(self):
85        return self.line
86
87
88def create_file_path(path):
89    dirs = []
90    while 1:
91        parent = os.path.dirname(path)
92        #print "parent: %s <- %s" % (parent, path)
93        if parent == "/" or parent == "":
94            break
95        dirs.append(parent)
96        path = parent
97
98    dirs.reverse()
99    for dir in dirs:
100        #print "dir %s" % dir
101        if os.path.isdir(dir):
102            continue
103        os.mkdir(dir)
104
105def walk_source_files(paths,callback,args,excludes=[]):
106    """recursively walk a list of paths and files, only keeping the source files in directories"""
107    for path in paths:
108        if len(path) > 0 and path[0] == '@':
109            # this is the name of another file, include it and parse it
110            path = path[1:]
111            if os.path.exists(path):
112                for line in open(path):
113                    if len(line) > 0 and line[-1] == '\n':
114                        line = line[:-1]
115                    walk_source_files([line],callback,args,excludes)
116            continue
117        if not os.path.isdir(path):
118            callback(path,args)
119        else:
120            for root, dirs, files in os.walk(path):
121                #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
122                if len(excludes):
123                    for d in dirs[:]:
124                        if os.path.join(root,d) in excludes:
125                            dirs.remove(d)
126                for f in files:
127                    r, ext = os.path.splitext(f)
128                    if ext in [ ".h", ".c", ".cpp", ".S" ]:
129                        callback( "%s/%s" % (root,f), args )
130
131def cleanup_dir(path):
132    """create a directory if needed, and ensure that it is totally empty
133       by removing any existing content in it"""
134    if not os.path.exists(path):
135        os.mkdir(path)
136    else:
137        for root, dirs, files in os.walk(path, topdown=False):
138            if root.endswith("kernel_headers/"):
139                # skip 'kernel_headers'
140                continue
141            for name in files:
142                os.remove(os.path.join(root, name))
143            for name in dirs:
144                os.rmdir(os.path.join(root, name))
145
146def update_file( path, newdata ):
147    """update a file on disk, only if its content has changed"""
148    if os.path.exists( path ):
149        try:
150            f = open( path, "r" )
151            olddata = f.read()
152            f.close()
153        except:
154            D("update_file: cannot read existing file '%s'" % path)
155            return 0
156
157        if oldata == newdata:
158            D2("update_file: no change to file '%s'" % path )
159            return 0
160
161        update = 1
162    else:
163        try:
164            create_file_path(path)
165        except:
166            D("update_file: cannot create path to '%s'" % path)
167            return 0
168
169    f = open( path, "w" )
170    f.write( newdata )
171    f.close()
172
173    return 1
174
175
176class BatchFileUpdater:
177    """a class used to edit several files at once"""
178    def __init__(self):
179        self.old_files = set()
180        self.new_files = set()
181        self.new_data  = {}
182
183    def readFile(self,path):
184        #path = os.path.realpath(path)
185        if os.path.exists(path):
186            self.old_files.add(path)
187
188    def readDir(self,path):
189        #path = os.path.realpath(path)
190        for root, dirs, files in os.walk(path):
191            for f in files:
192                dst = "%s/%s" % (root,f)
193                self.old_files.add(dst)
194
195    def editFile(self,dst,data):
196        """edit a destination file. if the file is not mapped from a source,
197           it will be added. return 0 if the file content wasn't changed,
198           1 if it was edited, or 2 if the file is new"""
199        #dst = os.path.realpath(dst)
200        result = 1
201        if os.path.exists(dst):
202            f = open(dst, "r")
203            olddata = f.read()
204            f.close()
205            if olddata == data:
206                self.old_files.remove(dst)
207                return 0
208        else:
209            result = 2
210
211        self.new_data[dst] = data
212        self.new_files.add(dst)
213        return result
214
215    def getChanges(self):
216        """determine changes, returns (adds, deletes, edits)"""
217        adds    = set()
218        edits   = set()
219        deletes = set()
220
221        for dst in self.new_files:
222            if not (dst in self.old_files):
223                adds.add(dst)
224            else:
225                edits.add(dst)
226
227        for dst in self.old_files:
228            if not dst in self.new_files:
229                deletes.add(dst)
230
231        return (adds, deletes, edits)
232
233    def _writeFile(self,dst):
234        if not os.path.exists(os.path.dirname(dst)):
235            create_file_path(dst)
236        f = open(dst, "w")
237        f.write(self.new_data[dst])
238        f.close()
239
240    def updateFiles(self):
241        adds, deletes, edits = self.getChanges()
242
243        for dst in sorted(adds):
244            self._writeFile(dst)
245
246        for dst in sorted(edits):
247            self._writeFile(dst)
248
249        for dst in sorted(deletes):
250            os.remove(dst)
251
252    def updateGitFiles(self):
253        adds, deletes, edits = self.getChanges()
254
255        if adds:
256            for dst in sorted(adds):
257                self._writeFile(dst)
258            commands.getoutput("git add " + " ".join(adds))
259
260        if deletes:
261            commands.getoutput("git rm " + " ".join(deletes))
262
263        if edits:
264            for dst in sorted(edits):
265                self._writeFile(dst)
266            commands.getoutput("git add " + " ".join(edits))
267