upload tizen1.0 source
[kernel/linux-2.6.36.git] / debian / lib / python / debian_linux / patches.py
1 import glob, os, shutil
2
3 class Operation(object):
4     def __init__(self, name, data):
5         self.name, self.data = name, data
6
7     def __call__(self, dir = '.', reverse = False):
8         try:
9             if not reverse:
10                 self.do(dir)
11             else:
12                 self.do_reverse(dir)
13             self._log(True)
14         except:
15             self._log(False)
16             raise
17
18     def _log(self, result):
19         if result:
20             s = "OK"
21         else:
22             s = "FAIL"
23         print """  (%s) %-4s %s""" % (self.operation, s, self.name)
24
25     def do(self, dir):
26         raise NotImplementedError
27
28     def do_reverse(self, dir):
29         raise NotImplementedError
30
31 class OperationPatch(Operation):
32     def __init__(self, name, fp, data):
33         super(OperationPatch, self).__init__(name, data)
34         self.fp = fp
35
36     def _call(self, dir, extraargs):
37         cmdline = "cd %s; patch -p1 -f -s -t --no-backup-if-mismatch %s" % (dir, extraargs)
38         f = os.popen(cmdline, 'wb')
39         shutil.copyfileobj(self.fp, f)
40         if f.close():
41             raise RuntimeError("Patch failed")
42
43     def patch_push(self, dir):
44         self._call(dir, '--fuzz=1')
45
46     def patch_pop(self, dir):
47         self._call(dir, '-R')
48
49 class OperationPatchPush(OperationPatch):
50     operation = '+'
51
52     do = OperationPatch.patch_push
53     do_reverse = OperationPatch.patch_pop
54
55 class OperationPatchPop(OperationPatch):
56     operation = '-'
57
58     do = OperationPatch.patch_pop
59     do_reverse = OperationPatch.patch_push
60
61 class SubOperation(Operation):
62     def _log(self, result):
63         if result:
64             s = "OK"
65         else:
66             s = "FAIL"
67         print """    %-10s %-4s %s""" % ('(%s)' % self.operation, s, self.name)
68
69 class SubOperationFilesRemove(SubOperation):
70     operation = "remove"
71
72     def do(self, dir):
73         name = os.path.join(dir, self.name)
74         for n in glob.iglob(name):
75             if os.path.isdir(n):
76                 shutil.rmtree(n)
77             else:
78                 os.unlink(n)
79
80 class SubOperationFilesUnifdef(SubOperation):
81     operation = "unifdef"
82
83     def do(self, dir):
84         filename = os.path.join(dir, self.name)
85         cmdline = "unifdef %s %s" % (filename, ' '.join(self.data))
86         f = os.popen(cmdline, 'rb')
87         data = f.read()
88         ret = f.close()
89         if ret is None:
90             raise RuntimeError("unifdef of %s removed nothing" % self.name)
91         elif ret != 256:
92             raise RuntimeError("unifdef failed")
93         f1 = file(filename, 'wb')
94         f1.write(data)
95         f1.close()
96
97 class OperationFiles(Operation):
98     operation = 'X'
99
100     suboperations = {
101         'remove': SubOperationFilesRemove,
102         'rm': SubOperationFilesRemove,
103         'unifdef': SubOperationFilesUnifdef,
104     }
105
106     def __init__(self, name, fp, data):
107         super(OperationFiles, self).__init__(name, data)
108
109         ops = []
110
111         for line in fp:
112             line = line.strip()
113             if not line or line[0] == '#':
114                 continue
115
116             items = line.split()
117             operation, filename = items[:2]
118             data = items[2:]
119
120             if operation not in self.suboperations:
121                 raise RuntimeError('Undefined operation "%s" in series %s' % (operation, name))
122
123             ops.append(self.suboperations[operation](filename, data))
124
125         self.ops = ops
126
127     def do(self, dir):
128         for i in self.ops:
129             i(dir = dir)
130
131 class PatchSeries(list):
132     operations = {
133         '+': OperationPatchPush,
134         '-': OperationPatchPop,
135         'X': OperationFiles,
136     }
137
138     def __init__(self, name, root, fp):
139         self.name, self.root = name, root
140
141         from gzip import GzipFile
142         from bz2 import BZ2File
143
144         for line in fp:
145             line = line.strip()
146
147             if not len(line) or line[0] == '#':
148                 continue
149
150             items = line.split(' ')
151             operation, filename = items[:2]
152             data = items[2:]
153
154             if operation in self.operations:
155                 f = os.path.join(self.root, filename)
156                 for suffix, cls in (('', file), ('.bz2', BZ2File), ('.gz', GzipFile)):
157                     f1 = f + suffix
158                     if os.path.exists(f1):
159                         fp = cls(f1)
160                         break
161                 else:
162                     raise RuntimeError("Can't find patch %s for series %s" % (filename, self.name))
163             else:
164                 raise RuntimeError('Undefined operation "%s" in series %s' % (operation, name))
165
166             self.append(self.operations[operation](filename, fp, data))
167
168     def __call__(self, cond = bool, dir = '.', reverse = False):
169         if not reverse:
170             l = self
171         else:
172             l = self[::-1]
173         for i in l:
174             if cond(i):
175                 i(dir = dir, reverse = reverse)
176
177     def __repr__(self):
178         return '<%s object for %s>' % (self.__class__.__name__, self.name)
179
180 class PatchSeriesList(list):
181     def __call__(self, cond = bool, reverse = False):
182         if not reverse:
183             l = self
184         else:
185             l = self[::-1]
186         for i in l:
187             if reverse:
188                 print "--> Try to unapply %s." % i.name
189             else:
190                 print "--> Try to apply %s." % i.name
191             i(cond = cond, reverse = reverse)
192             if reverse:
193                 print "--> %s fully unapplied." % i.name
194             else:
195                 print "--> %s fully applied." % i.name
196
197     @classmethod
198     def read(cls, home, files):
199         ret = cls()
200         for i in files:
201             try:
202                 fp = file(os.path.join(home, 'series', i))
203                 ret.append(PatchSeries(i, home, fp))
204             except IOError:
205                 pass
206         return ret
207