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 find_program_dir():
17    return os.path.dirname(sys.argv[0])
18
19
20class StringOutput:
21    def __init__(self):
22        self.line = ""
23
24    def write(self,msg):
25        self.line += msg
26        logging.debug("write '%s'" % msg)
27
28    def get(self):
29        return self.line
30
31
32def create_file_path(path):
33    dirs = []
34    while 1:
35        parent = os.path.dirname(path)
36        #print "parent: %s <- %s" % (parent, path)
37        if parent == "/" or parent == "":
38            break
39        dirs.append(parent)
40        path = parent
41
42    dirs.reverse()
43    for dir in dirs:
44        #print "dir %s" % dir
45        if os.path.isdir(dir):
46            continue
47        os.mkdir(dir)
48
49
50class BatchFileUpdater:
51    """a class used to edit several files at once"""
52    def __init__(self):
53        self.old_files = set()
54        self.new_files = set()
55        self.new_data  = {}
56
57    def readFile(self,path):
58        #path = os.path.realpath(path)
59        if os.path.exists(path):
60            self.old_files.add(path)
61
62    def readDir(self,path):
63        #path = os.path.realpath(path)
64        for root, dirs, files in os.walk(path):
65            for f in files:
66                dst = "%s/%s" % (root,f)
67                self.old_files.add(dst)
68
69    def editFile(self,dst,data):
70        """edit a destination file. if the file is not mapped from a source,
71           it will be added. return 0 if the file content wasn't changed,
72           1 if it was edited, or 2 if the file is new"""
73        #dst = os.path.realpath(dst)
74        result = 1
75        if os.path.exists(dst):
76            f = open(dst, "r")
77            olddata = f.read()
78            f.close()
79            if olddata == data:
80                self.old_files.remove(dst)
81                return 0
82        else:
83            result = 2
84
85        self.new_data[dst] = data
86        self.new_files.add(dst)
87        return result
88
89    def getChanges(self):
90        """determine changes, returns (adds, deletes, edits)"""
91        adds    = set()
92        edits   = set()
93        deletes = set()
94
95        for dst in self.new_files:
96            if not (dst in self.old_files):
97                adds.add(dst)
98            else:
99                edits.add(dst)
100
101        for dst in self.old_files:
102            if not dst in self.new_files:
103                deletes.add(dst)
104
105        return (adds, deletes, edits)
106
107    def _writeFile(self,dst):
108        if not os.path.exists(os.path.dirname(dst)):
109            create_file_path(dst)
110        f = open(dst, "w")
111        f.write(self.new_data[dst])
112        f.close()
113
114    def updateFiles(self):
115        adds, deletes, edits = self.getChanges()
116
117        for dst in sorted(adds):
118            self._writeFile(dst)
119
120        for dst in sorted(edits):
121            self._writeFile(dst)
122
123        for dst in sorted(deletes):
124            os.remove(dst)
125
126    def updateGitFiles(self):
127        adds, deletes, edits = self.getChanges()
128
129        if adds:
130            for dst in sorted(adds):
131                self._writeFile(dst)
132            commands.getoutput("git add " + " ".join(adds))
133
134        if deletes:
135            commands.getoutput("git rm " + " ".join(deletes))
136
137        if edits:
138            for dst in sorted(edits):
139                self._writeFile(dst)
140            commands.getoutput("git add " + " ".join(edits))
141