#! /usr/bin/python # # Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. import os import tempfile import shutil import pmpkg from util import * def _mkfilelist(files): """Generate a list of files from the list supplied as an argument. Each path is decomposed to generate the list of all directories leading to the file. Example with 'usr/local/bin/dummy': The resulting list will be usr/ usr/local/ usr/local/bin/ usr/local/bin/dummy """ i = [] for f in files: dir = getfilename(f) i.append(dir) while "/" in dir: [dir, tmp] = dir.rsplit("/", 1) if not dir + "/" in files: i.append(dir + "/") i.sort() return i def _mkbackuplist(backup): """ """ return ["%s\t%s" % (getfilename(i), mkmd5sum(i)) for i in backup] def _getsection(fd): """ """ i = [] while 1: line = fd.readline().strip("\n") if not line: break i.append(line) return i def _mksection(title, data): """ """ s = "" if isinstance(data, list): s = "\n".join(data) else: s = data return "%%%s%%\n" \ "%s\n" % (title, s) class pmdb: """Database object """ def __init__(self, treename, dbdir): self.treename = treename self.dbdir = dbdir self.pkgs = [] def __str__(self): return "%s" % self.treename def getpkg(self, name): """ """ for pkg in self.pkgs: if name == pkg.name: return pkg def db_read(self, name): """ """ path = os.path.join(self.dbdir, self.treename) if not os.path.isdir(path): return None dbentry = "" for roots, dirs, files in os.walk(path): for i in dirs: [pkgname, pkgver, pkgrel] = i.rsplit("-", 2) if pkgname == name: dbentry = i break if not dbentry: return None path = os.path.join(path, dbentry) [pkgname, pkgver, pkgrel] = dbentry.rsplit("-", 2) pkg = pmpkg.pmpkg(pkgname, pkgver + "-" + pkgrel) # desc filename = os.path.join(path, "desc") fd = file(filename, "r") while 1: line = fd.readline() if not line: break line = line.strip("\n") if line == "%DESC%": pkg.desc = fd.readline().strip("\n") elif line == "%GROUPS%": pkg.groups = _getsection(fd) elif line == "%URL%": pkg.url = fd.readline().strip("\n") elif line == "%LICENSE%": pkg.license = _getsection(fd) elif line == "%ARCH%": pkg.arch = fd.readline().strip("\n") elif line == "%BUILDDATE%": pkg.builddate = fd.readline().strip("\n") elif line == "%INSTALLDATE%": pkg.installdate = fd.readline().strip("\n") elif line == "%PACKAGER%": pkg.packager = fd.readline().strip("\n") elif line == "%REASON%": pkg.reason = int(fd.readline().strip("\n")) elif line == "%SIZE%" or line == "%CSIZE%": pkg.size = int(fd.readline().strip("\n")) elif line == "%MD5SUM%": pkg.md5sum = fd.readline().strip("\n") elif line == "%REPLACES%": pkg.replaces = _getsection(fd) elif line == "%FORCE%": fd.readline() pkg.force = 1 fd.close() pkg.checksum["desc"] = getmd5sum(filename) pkg.mtime["desc"] = getmtime(filename) # files filename = os.path.join(path, "files") fd = file(filename, "r") while 1: line = fd.readline() if not line: break line = line.strip("\n") if line == "%FILES%": while line: line = fd.readline().strip("\n") if line and line[-1] != "/": pkg.files.append(line) if line == "%BACKUP%": pkg.backup = _getsection(fd) fd.close() pkg.checksum["files"] = getmd5sum(filename) pkg.mtime["files"] = getmtime(filename) # depends filename = os.path.join(path, "depends") fd = file(filename, "r") while 1: line = fd.readline() if not line: break line = line.strip("\n") if line == "%DEPENDS%": pkg.depends = _getsection(fd) elif line == "%REQUIREDBY%": pkg.requiredby = _getsection(fd) elif line == "%CONFLICTS%": pkg.conflicts = _getsection(fd) elif line == "%PROVIDES%": pkg.provides = _getsection(fd) elif line == "%REPLACES%": pkg.replaces = _getsection(fd) elif line == "%FORCE%": fd.readline() pkg.force = 1 fd.close() pkg.checksum["depends"] = getmd5sum(filename) pkg.mtime["depends"] = getmtime(filename) # install filename = os.path.join(path, "install") if os.path.isfile(filename): pkg.checksum["install"] = getmd5sum(filename) pkg.mtime["install"] = getmtime(filename) return pkg # # db_write is used to add both 'local' and 'sync' db entries # def db_write(self, pkg): """ """ path = os.path.join(self.dbdir, self.treename, pkg.fullname()) if not os.path.isdir(path): os.makedirs(path); # desc # for local db entries: name, version, desc, groups, url, license, # arch, builddate, installdate, packager, # size, reason # for sync entries: name, version, desc, groups, csize, md5sum, # replaces, force data = [_mksection("NAME", pkg.name)] data.append(_mksection("VERSION", pkg.version)) if pkg.desc: data.append(_mksection("DESC", pkg.desc)) if pkg.groups: data.append(_mksection("GROUPS", pkg.groups)) if self.treename == "local": if pkg.url: data.append(_mksection("URL", pkg.url)) if pkg.license: data.append(_mksection("LICENSE", pkg.license)) if pkg.arch: data.append(_mksection("ARCH", pkg.arch)) if pkg.builddate: data.append(_mksection("BUILDDATE", pkg.builddate)) if pkg.installdate: data.append(_mksection("INSTALLDATE", pkg.installdate)) if pkg.packager: data.append(_mksection("PACKAGER", pkg.packager)) if pkg.size: data.append(_mksection("SIZE", pkg.size)) if pkg.reason: data.append(_mksection("REASON", pkg.reason)) else: if pkg.csize: data.append(_mksection("CSIZE", pkg.csize)) if pkg.md5sum: data.append(_mksection("MD5SUM", pkg.md5sum)) if data: data.append("") filename = os.path.join(path, "desc") mkfile(filename, "\n".join(data)) pkg.checksum["desc"] = getmd5sum(filename) pkg.mtime["desc"] = getmtime(filename) # files # for local entries, fields are: files, backup # for sync ones: none if self.treename == "local": data = [] if pkg.files: data.append(_mksection("FILES", _mkfilelist(pkg.files))) if pkg.backup: data.append(_mksection("BACKUP", _mkbackuplist(pkg.backup))) if data: data.append("") filename = os.path.join(path, "files") mkfile(filename, "\n".join(data)) pkg.checksum["files"] = getmd5sum(filename) pkg.mtime["files"] = getmtime(filename) # depends # for local db entries: depends, requiredby, conflicts, provides # for sync ones: depends, conflicts, provides data = [] if pkg.depends: data.append(_mksection("DEPENDS", pkg.depends)) if self.treename == "local": if pkg.requiredby: data.append(_mksection("REQUIREDBY", pkg.requiredby)) if pkg.conflicts: data.append(_mksection("CONFLICTS", pkg.conflicts)) if pkg.provides: data.append(_mksection("PROVIDES", pkg.provides)) if not self.treename == "local": if pkg.replaces: data.append(_mksection("REPLACES", pkg.replaces)) if pkg.force: data.append(_mksection("FORCE", "")) if data: data.append("") filename = os.path.join(path, "depends") mkfile(filename, "\n".join(data)) pkg.checksum["depends"] = getmd5sum(filename) pkg.mtime["depends"] = getmtime(filename) # install if self.treename == "local": empty = 1 for value in pkg.install.values(): if value: empty = 0 if not empty: filename = os.path.join(path, "install") mkinstallfile(filename, pkg.install) pkg.checksum["install"] = getmd5sum(filename) pkg.mtime["install"] = getmtime(filename) def gensync(self, path): """ """ curdir = os.getcwd() tmpdir = tempfile.mkdtemp() os.chdir(tmpdir) for pkg in self.pkgs: mkdescfile(pkg.fullname(), pkg) # Generate database archive os.makedirs(path, 0755) archive = os.path.join(path, "%s%s" % (self.treename, PM_EXT_DB)) os.system("tar zcf %s *" % archive) os.chdir(curdir) shutil.rmtree(tmpdir) def ispkgmodified(self, pkg): """ """ modified = 0 oldpkg = self.getpkg(pkg.name) if not oldpkg: return 0 #dbg("oldpkg.checksum : %s" % oldpkg.checksum) #dbg("oldpkg.mtime : %s" % oldpkg.mtime) for key in pkg.mtime.keys(): if key == "install" \ and oldpkg.mtime[key] == (0, 0, 0) \ and pkg.mtime[key] == (0, 0, 0): continue if not oldpkg.mtime[key][1:3] == pkg.mtime[key][1:3]: modified += 1 return modified if __name__ == "__main__": db = pmdb("local") print db # vim: set ts=4 sw=4 et: