]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/contrib/buildscripts/openzaurus/feed-split/ipkg.py
ppp-dialin: don't error out in postinst if ppp user already exists. Fixes Bug #1625.
[familiar-h63xx-build.git] / org.handhelds.familiar / contrib / buildscripts / openzaurus / feed-split / ipkg.py
1 #!/usr/bin/env python
2 #   Copyright (C) 2001 Alexander S. Guy <a7r@andern.org>
3 #                      Andern Research Labs
4 #
5 #   This program is free software; you can redistribute it and/or modify
6 #   it under the terms of the GNU General Public License as published by
7 #   the Free Software Foundation; either version 2, or (at your option)
8 #   any later version.
9 #
10 #   This program is distributed in the hope that it will be useful,
11 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #   GNU General Public License for more details.
14 #
15 #   You should have received a copy of the GNU General Public License
16 #   along with this program; if not, write to the Free Software
17 #   Foundation, Inc., 59 Temple Place - Suite 330,
18 #   Boston, MA 02111-1307, USA.  */
19 #
20 #   Copyright 2001, Russell Nelson <ipkg.py@russnelson.com>
21 #   Added reading in of packages.
22 #   Added missing package information fields.
23 #   Changed render_control() to __repr__().
24 #
25 # Current Issues:
26 #    The API doesn't validate package information fields.  It should be
27 #        throwing exceptions in the right places.
28 #    Executions of tar could silently fail.
29 #    Executions of tar *do* fail, and loudly, because you have to specify a full filename,
30 #        and tar complains if any files are missing, and the ipkg spec doesn't require
31 #        people to say "./control.tar.gz" or "./control" when they package files.
32 #        It would be much better to require ./control or disallow ./control (either)
33 #        rather than letting people pick.  Some freedoms aren't worth their cost.
34
35 import tempfile
36 import os
37 import sys
38 import glob
39 import md5
40 import re
41 import string
42 import commands
43 from stat import ST_SIZE
44
45 class Package:
46     """A class for creating objects to manipulate (e.g. create) ipkg
47        packages."""
48     def __init__(self, fn=None):
49         self.package = None
50         self.version = None
51         self.architecture = None
52         self.maintainer = None
53         self.source = None
54         self.description = None
55         self.depends = None
56         self.provides = None
57         self.replaces = None
58         self.conflicts = None
59         self.recommends = None
60         self.suggests = None
61         self.section = None
62         self.filename_header = None
63         self.file_list = []
64         self.md5 = None
65         self.size = None
66         self.installed_size = None
67         self.filename = None
68         self.isdeb = 0
69
70         if fn:
71             # see if it is deb format
72             f = open(fn, "r")
73             magic = f.read(4)
74             f.close()
75             if (magic == "!<ar"):
76                 self.isdeb = 1
77
78             # compute the MD5.
79             f = open(fn, "r")
80             sum = md5.new()
81             while 1:
82                 data = f.read(1024)
83                 if not data: break
84                 sum.update(data)
85             f.close()
86             if sys.version[:1] > '2':
87                 # when using Python 2.0 or newer
88                 self.md5 = sum.hexdigest() 
89             else:
90                 self.md5 = string.join(map((lambda x:"%02x" % ord(x)),sum.digest()),'')
91             stat = os.stat(fn)
92             self.size = stat[ST_SIZE]
93             self.filename = os.path.basename(fn)
94             ## sys.stderr.write("  extracting control.tar.gz from %s\n"% (fn,)) 
95             if self.isdeb:
96                 control = os.popen("ar p "+fn+" control.tar.gz | tar xfzO - '*control'","r")
97             else:
98                 control = os.popen("tar xfzO "+fn+" '*control.tar.gz' | tar xfzO - '*control'","r")
99             line = control.readline()
100             while 1:
101                 if not line: break
102                 line = string.rstrip(line)
103                 lineparts = re.match(r'([\w-]*?):\s*(.*)', line)
104                 if lineparts:
105                     name = string.lower(lineparts.group(1))
106                     value = lineparts.group(2)
107                     while 1:
108                         line = control.readline()
109                         if not line: break
110                         if line[0] != ' ': break
111                         line = string.rstrip(line)
112                         value = value + '\n' + line
113                     # don't allow package to override its own filename
114                     if name == "filename":
115                         self.filename_header = value
116                     else:
117                         if self.__dict__.has_key(name):
118                             self.__dict__[name] = value
119                 else:
120                     line = control.readline()
121             control.close()
122             if self.isdeb:
123                 data = os.popen("ar p "+fn+" data.tar.gz | tar tfz -","r")
124             else:
125                 data = os.popen("tar xfzO "+fn+" '*data.tar.gz' | tar tfz -","r")
126             while 1:
127                 line = data.readline()
128                 if not line: break
129                 self.file_list.append(string.rstrip(line))
130             data.close()
131
132         self.scratch_dir = None
133         self.file_dir = None
134         self.meta_dir = None
135
136     def read_control(self, control):
137         import os
138
139         line = control.readline()
140         while 1:
141             if not line: break
142             line = string.rstrip(line)
143             lineparts = re.match(r'([\w-]*?):\s*(.*)', line)
144             if lineparts:
145                 name = string.lower(lineparts.group(1))
146                 value = lineparts.group(2)
147                 while 1:
148                     line = control.readline()
149                     if not line: break
150                     if line[0] != ' ': break
151                     value = value + '\n' + line
152                 if name == 'size':
153                     self.size = int(value)
154                 elif self.__dict__.has_key(name):
155                     self.__dict__[name] = value
156                 if line[0] == '\n':
157                     return # consumes one blank line at end of package descriptoin
158             else:
159                 line = control.readline()
160                 pass
161         return    
162
163     def _setup_scratch_area(self):
164         self.scratch_dir = "%s/%sipkg" % (tempfile.gettempdir(),
165                                            tempfile.gettempprefix())
166         self.file_dir = "%s/files" % (self.scratch_dir)
167         self.meta_dir = "%s/meta" % (self.scratch_dir)
168
169         os.mkdir(self.scratch_dir)
170         os.mkdir(self.file_dir)
171         os.mkdir(self.meta_dir)
172
173     def set_package(self, package):
174         self.package = package
175
176     def get_package(self):
177         return self.package
178                 
179     def set_version(self, version):
180         self.version = version
181
182     def get_version(self):
183         return self.version
184
185     def set_architecture(self, architecture):
186         self.architecture = architecture
187
188     def get_architecture(self):
189         return self.architecture
190
191     def set_maintainer(self, maintainer):
192         self.maintainer = maintainer
193
194     def get_maintainer(self):
195         return self.maintainer
196
197     def set_source(self, source):
198         self.source = source
199
200     def get_source(self):
201         return self.source
202
203     def set_description(self, description):
204         self.description = description
205
206     def get_description(self):
207         return self.description
208
209     def set_depends(self, depends):
210         self.depends = depends
211
212     def get_depends(self, depends):
213         return self.depends
214
215     def set_provides(self, provides):
216         self.provides = provides
217
218     def get_provides(self, provides):
219         return self.provides
220
221     def set_replaces(self, replaces):
222         self.replaces = replaces
223
224     def get_replaces(self, replaces):
225         return self.replaces
226
227     def set_conflicts(self, conflicts):
228         self.conflicts = conflicts
229
230     def get_conflicts(self, conflicts):
231         return self.conflicts
232
233     def set_suggests(self, suggests):
234         self.suggests = suggests
235
236     def get_suggests(self, suggests):
237         return self.suggests
238
239     def set_section(self, section):
240         self.section = section
241
242     def get_section(self, section):
243         return self.section
244
245     def get_file_list(self):
246         return self.file_list
247
248     def write_package(self, dirname):
249         buf = self.render_control()
250         file = open("%s/control" % self.meta_dir, 'w')
251         file.write(buf)
252
253         self._setup_scratch_area()
254         cmd = "cd %s ; tar cvfz %s/control.tar.gz control" % (self.meta_dir,
255                                                               self.scratch_dir)
256
257         cmd_out, cmd_in, cmd_err = os.popen3(cmd)
258         
259         while cmd_err.readline() != "":
260             pass
261
262         cmd_out.close()
263         cmd_in.close()
264         cmd_err.close()
265
266         bits = "control.tar.gz"
267
268         if self.file_list:
269                 cmd = "cd %s ; tar cvfz %s/data.tar.gz" % (self.file_dir,
270                                                            self.scratch_dir)
271
272                 cmd_out, cmd_in, cmd_err = os.popen3(cmd)
273
274                 while cmd_err.readline() != "":
275                     pass
276
277                 cmd_out.close()
278                 cmd_in.close()
279                 cmd_err.close()
280
281                 bits = bits + " data.tar.gz"
282
283         file = "%s_%s_%s.ipk" % (self.package, self.version, self.architecture)
284         cmd = "cd %s ; tar cvfz %s/%s %s" % (self.scratch_dir,
285                                              dirname,
286                                              file,
287                                              bits)
288
289         cmd_out, cmd_in, cmd_err = os.popen3(cmd)
290
291         while cmd_err.readline() != "":
292             pass
293
294         cmd_out.close()
295         cmd_in.close()
296         cmd_err.close()
297
298     def __repr__(self):
299         out = ""
300
301         # XXX - Some checks need to be made, and some exceptions
302         #       need to be thrown. -- a7r
303
304         if self.package: out = out + "Package: %s\n" % (self.package)
305         if self.version: out = out + "Version: %s\n" % (self.version)
306         if self.depends: out = out + "Depends: %s\n" % (self.depends)
307         if self.provides: out = out + "Provides: %s\n" % (self.provides)
308         if self.replaces: out = out + "Replaces: %s\n" % (self.replaces)
309         if self.conflicts: out = out + "Conflicts: %s\n" % (self.conflicts)
310         if self.suggests: out = out + "Suggests: %s\n" % (self.suggests)
311         if self.recommends: out = out + "Recommends: %s\n" % (self.recommends)
312         if self.section: out = out + "Section: %s\n" % (self.section)
313         if self.architecture: out = out + "Architecture: %s\n" % (self.architecture)
314         if self.maintainer: out = out + "Maintainer: %s\n" % (self.maintainer)
315         if self.md5: out = out + "MD5Sum: %s\n" % (self.md5)
316         if self.size: out = out + "Size: %d\n" % int(self.size)
317         if self.installed_size: out = out + "InstalledSize: %d\n" % int(self.installed_size)
318         if self.filename: out = out + "Filename: %s\n" % (self.filename)
319         if self.source: out = out + "Source: %s\n" % (self.source)
320         if self.description: out = out + "Description: %s\n" % (self.description)
321         out = out + "\n"
322
323         return out
324
325     def __del__(self):
326         # XXX - Why is the `os' module being yanked out before Package objects
327         #       are being destroyed?  -- a7r
328         pass
329
330 class Packages:
331     """A currently unimplemented wrapper around the ipkg utility."""
332     def __init__(self):
333         self.packages = {}
334         return
335
336     def add_package(self, pkg):
337         package = pkg.package
338         arch = pkg.architecture
339         #name = ("%s:%s" % (package, arch))
340         name = ("%s" % (package))
341         if (not self.packages.has_key(name)):
342             self.packages[name] = pkg
343         (s, outtext) = commands.getstatusoutput("ipkg-compare-versions %s '>' %s" % (pkg.version, self.packages[name].version))    
344         if (s == 0):
345             self.packages[name] = pkg
346             return 0
347         else:
348             return 1
349
350     def read_packages_file(self, fn):
351         f = open(fn, "r")
352         while 1:
353             pkg = Package()
354             pkg.read_control(f)
355             if pkg.get_package():
356                 self.add_package(pkg)
357             else:
358                 break
359         f.close()    
360         return
361
362     def write_packages_file(self, fn):
363         f = open(fn, "w")
364         names = self.packages.keys()
365         names.sort()
366         for name in names:
367             f.write(self.packages[name].__repr__())
368         return    
369
370     def keys(self):
371         return self.packages.keys()
372
373     def __getitem__(self, key):
374         return self.packages[key]
375
376 if __name__ == "__main__":
377     package = Package()
378
379     package.set_package("FooBar")
380     package.set_version("0.1-fam1")
381     package.set_architecture("arm")
382     package.set_maintainer("Testing <testing@testing.testing>")
383     package.set_depends("libc")
384     package.set_description("A test of the APIs.")
385
386     print "<"
387     sys.stdout.write(package)
388     print ">"
389
390     package.write_package("/tmp")
391