makepkg: add functions for backup and restore of package fields
[pacman-ng.git] / pactest / pmdb.py
blobcfa146bd64aa2dbe70030e63e9ef344288dd3535
1 #! /usr/bin/python
3 # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com>
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 of the License, or
8 # (at your option) any later version.
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.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import os
20 import tempfile
21 import shutil
22 import tarfile
24 import pmpkg
25 from util import *
28 def _mkfilelist(files):
29 """Generate a list of files from the list supplied as an argument.
31 Each path is decomposed to generate the list of all directories leading
32 to the file.
34 Example with 'usr/local/bin/dummy':
35 The resulting list will be
36 usr/
37 usr/local/
38 usr/local/bin/
39 usr/local/bin/dummy
40 """
41 i = []
42 for f in files:
43 dir = getfilename(f)
44 i.append(dir)
45 while "/" in dir:
46 [dir, tmp] = dir.rsplit("/", 1)
47 if not dir + "/" in files:
48 i.append(dir + "/")
49 i.sort()
50 return i
52 def _mkbackuplist(backup):
53 """
54 """
55 return ["%s\t%s" % (getfilename(i), mkmd5sum(i)) for i in backup]
57 def _getsection(fd):
58 """
59 """
60 i = []
61 while 1:
62 line = fd.readline().strip("\n")
63 if not line:
64 break
65 i.append(line)
66 return i
68 def _mksection(title, data):
69 """
70 """
71 s = ""
72 if isinstance(data, list):
73 s = "\n".join(data)
74 else:
75 s = data
76 return "%%%s%%\n" \
77 "%s\n" % (title, s)
80 class pmdb:
81 """Database object
82 """
84 def __init__(self, treename, dbdir):
85 self.treename = treename
86 self.dbdir = dbdir
87 self.pkgs = []
89 def __str__(self):
90 return "%s" % self.treename
92 def getpkg(self, name):
93 """
94 """
95 for pkg in self.pkgs:
96 if name == pkg.name:
97 return pkg
99 def db_read(self, name):
103 path = os.path.join(self.dbdir, self.treename)
104 if not os.path.isdir(path):
105 return None
107 dbentry = ""
108 for roots, dirs, files in os.walk(path):
109 for i in dirs:
110 [pkgname, pkgver, pkgrel] = i.rsplit("-", 2)
111 if pkgname == name:
112 dbentry = i
113 break
114 if not dbentry:
115 return None
116 path = os.path.join(path, dbentry)
118 [pkgname, pkgver, pkgrel] = dbentry.rsplit("-", 2)
119 pkg = pmpkg.pmpkg(pkgname, pkgver + "-" + pkgrel)
121 # desc
122 filename = os.path.join(path, "desc")
123 if not os.path.isfile(filename):
124 print "invalid db entry found (desc missing) for pkg", pkgname
125 return None
126 fd = open(filename, "r")
127 while 1:
128 line = fd.readline()
129 if not line:
130 break
131 line = line.strip("\n")
132 if line == "%DESC%":
133 pkg.desc = fd.readline().strip("\n")
134 elif line == "%GROUPS%":
135 pkg.groups = _getsection(fd)
136 elif line == "%URL%":
137 pkg.url = fd.readline().strip("\n")
138 elif line == "%LICENSE%":
139 pkg.license = _getsection(fd)
140 elif line == "%ARCH%":
141 pkg.arch = fd.readline().strip("\n")
142 elif line == "%BUILDDATE%":
143 pkg.builddate = fd.readline().strip("\n")
144 elif line == "%INSTALLDATE%":
145 pkg.installdate = fd.readline().strip("\n")
146 elif line == "%PACKAGER%":
147 pkg.packager = fd.readline().strip("\n")
148 elif line == "%REASON%":
149 pkg.reason = int(fd.readline().strip("\n"))
150 elif line == "%SIZE%" or line == "%CSIZE%":
151 pkg.size = int(fd.readline().strip("\n"))
152 elif line == "%MD5SUM%":
153 pkg.md5sum = fd.readline().strip("\n")
154 elif line == "%REPLACES%":
155 pkg.replaces = _getsection(fd)
156 elif line == "%FORCE%":
157 fd.readline()
158 pkg.force = 1
159 fd.close()
160 pkg.checksum["desc"] = getmd5sum(filename)
161 pkg.mtime["desc"] = getmtime(filename)
163 # files
164 filename = os.path.join(path, "files")
165 if not os.path.isfile(filename):
166 print "invalid db entry found (files missing) for pkg", pkgname
167 return None
168 fd = open(filename, "r")
169 while 1:
170 line = fd.readline()
171 if not line:
172 break
173 line = line.strip("\n")
174 if line == "%FILES%":
175 while line:
176 line = fd.readline().strip("\n")
177 if line and line[-1] != "/":
178 pkg.files.append(line)
179 if line == "%BACKUP%":
180 pkg.backup = _getsection(fd)
181 fd.close()
182 pkg.checksum["files"] = getmd5sum(filename)
183 pkg.mtime["files"] = getmtime(filename)
185 # depends
186 filename = os.path.join(path, "depends")
187 if not os.path.isfile(filename):
188 print "invalid db entry found (depends missing) for pkg", pkgname
189 return None
190 fd = file(filename, "r")
191 while 1:
192 line = fd.readline()
193 if not line:
194 break
195 line = line.strip("\n")
196 if line == "%DEPENDS%":
197 pkg.depends = _getsection(fd)
198 elif line == "%OPTDEPENDS%":
199 pkg.optdepends = _getsection(fd)
200 elif line == "%CONFLICTS%":
201 pkg.conflicts = _getsection(fd)
202 elif line == "%PROVIDES%":
203 pkg.provides = _getsection(fd)
204 # TODO this was going to be changed, but isn't anymore
205 #elif line == "%REPLACES%":
206 # pkg.replaces = _getsection(fd)
207 #elif line == "%FORCE%":
208 # fd.readline()
209 # pkg.force = 1
210 fd.close()
211 pkg.checksum["depends"] = getmd5sum(filename)
212 pkg.mtime["depends"] = getmtime(filename)
214 # install
215 filename = os.path.join(path, "install")
216 if os.path.isfile(filename):
217 pkg.checksum["install"] = getmd5sum(filename)
218 pkg.mtime["install"] = getmtime(filename)
220 return pkg
223 # db_write is used to add both 'local' and 'sync' db entries
225 def db_write(self, pkg):
229 if self.treename == "local":
230 path = os.path.join(self.dbdir, self.treename, pkg.fullname())
231 else:
232 path = os.path.join(self.dbdir, "sync", self.treename, pkg.fullname())
233 mkdir(path)
235 # desc
236 # for local db entries: name, version, desc, groups, url, license,
237 # arch, builddate, installdate, packager,
238 # size, reason
239 # for sync entries: name, version, desc, groups, csize, md5sum,
240 # replaces, force
241 data = [_mksection("NAME", pkg.name)]
242 data.append(_mksection("VERSION", pkg.version))
243 if pkg.desc:
244 data.append(_mksection("DESC", pkg.desc))
245 if pkg.groups:
246 data.append(_mksection("GROUPS", pkg.groups))
247 if pkg.license:
248 data.append(_mksection("LICENSE", pkg.license))
249 if pkg.arch:
250 data.append(_mksection("ARCH", pkg.arch))
251 if pkg.builddate:
252 data.append(_mksection("BUILDDATE", pkg.builddate))
253 if pkg.packager:
254 data.append(_mksection("PACKAGER", pkg.packager))
255 if self.treename == "local":
256 if pkg.url:
257 data.append(_mksection("URL", pkg.url))
258 if pkg.installdate:
259 data.append(_mksection("INSTALLDATE", pkg.installdate))
260 if pkg.size:
261 data.append(_mksection("SIZE", pkg.size))
262 if pkg.reason:
263 data.append(_mksection("REASON", pkg.reason))
264 else:
265 data.append(_mksection("FILENAME", pkg.filename()))
266 if pkg.replaces:
267 data.append(_mksection("REPLACES", pkg.replaces))
268 if pkg.force:
269 data.append(_mksection("FORCE", ""))
270 if pkg.csize:
271 data.append(_mksection("CSIZE", pkg.csize))
272 if pkg.md5sum:
273 data.append(_mksection("MD5SUM", pkg.md5sum))
274 if data:
275 data.append("")
276 filename = os.path.join(path, "desc")
277 mkfile(filename, "\n".join(data))
278 pkg.checksum["desc"] = getmd5sum(filename)
279 pkg.mtime["desc"] = getmtime(filename)
281 # files
282 # for local entries, fields are: files, backup
283 # for sync ones: none
284 if self.treename == "local":
285 data = []
286 if pkg.files:
287 data.append(_mksection("FILES", _mkfilelist(pkg.files)))
288 if pkg.backup:
289 data.append(_mksection("BACKUP", _mkbackuplist(pkg.backup)))
290 if data:
291 data.append("")
292 filename = os.path.join(path, "files")
293 mkfile(filename, "\n".join(data))
294 pkg.checksum["files"] = getmd5sum(filename)
295 pkg.mtime["files"] = getmtime(filename)
297 # depends
298 # for local db entries: depends, conflicts, provides
299 # for sync ones: depends, conflicts, provides
300 data = []
301 if pkg.depends:
302 data.append(_mksection("DEPENDS", pkg.depends))
303 if pkg.optdepends:
304 data.append(_mksection("OPTDEPENDS", pkg.optdepends))
305 if pkg.conflicts:
306 data.append(_mksection("CONFLICTS", pkg.conflicts))
307 if pkg.provides:
308 data.append(_mksection("PROVIDES", pkg.provides))
309 #if self.treename != "local":
310 # if pkg.replaces:
311 # data.append(_mksection("REPLACES", pkg.replaces))
312 # if pkg.force:
313 # data.append(_mksection("FORCE", ""))
314 if data:
315 data.append("")
316 filename = os.path.join(path, "depends")
317 mkfile(filename, "\n".join(data))
318 pkg.checksum["depends"] = getmd5sum(filename)
319 pkg.mtime["depends"] = getmtime(filename)
321 # install
322 if self.treename == "local":
323 empty = 1
324 for value in pkg.install.values():
325 if value:
326 empty = 0
327 if not empty:
328 filename = os.path.join(path, "install")
329 mkinstallfile(filename, pkg.install)
330 pkg.checksum["install"] = getmd5sum(filename)
331 pkg.mtime["install"] = getmtime(filename)
333 def gensync(self, path):
337 curdir = os.getcwd()
338 tmpdir = tempfile.mkdtemp()
339 os.chdir(tmpdir)
341 for pkg in self.pkgs:
342 mkdescfile(pkg.fullname(), pkg)
344 # Generate database archive
345 mkdir(path)
346 archive = os.path.join(path, "%s%s" % (self.treename, PM_EXT_DB))
347 tar = tarfile.open(archive, "w:gz")
348 for root, dirs, files in os.walk('.'):
349 for d in dirs:
350 tar.add(os.path.join(root, d), recursive=False)
351 for f in files:
352 tar.add(os.path.join(root, f))
353 tar.close()
355 os.chdir(curdir)
356 shutil.rmtree(tmpdir)
358 def ispkgmodified(self, pkg):
362 modified = 0
364 oldpkg = self.getpkg(pkg.name)
365 if not oldpkg:
366 return 0
368 vprint("\toldpkg.checksum : %s" % oldpkg.checksum)
369 vprint("\toldpkg.mtime : %s" % oldpkg.mtime)
371 for key in pkg.mtime.keys():
372 if key == "install" \
373 and oldpkg.mtime[key] == (0, 0, 0) \
374 and pkg.mtime[key] == (0, 0, 0):
375 continue
376 if oldpkg.mtime[key][1:3] != pkg.mtime[key][1:3]:
377 modified += 1
379 return modified
382 if __name__ == "__main__":
383 db = pmdb("local")
384 print db
385 # vim: set ts=4 sw=4 et: