1
0
mirror of https://github.com/moparisthebest/pacman synced 2024-12-23 08:18:51 -05:00
pacman/pactest/pmdb.py
Chantry Xavier c465d9e848 pactest : Use tarfile module.
Previously, tar was called manually with os.system. This caused one fork per
package/db creation, which is costly, especially on cygwin. Besides, it also
caused some problems with directory with whitespaces (that could also be
fixed with quotes, but well..)
Using tarfile module is cleaner and more efficient, and still easy enough.

Benchmark (time make check) :
- windows / cygwin
prepatch:
real    6m36.360s
user    2m28.914s
sys     2m35.866s
postpatch:
real    5m25.428s
user    1m26.029s
sys     2m0.006s

- linux
prepatch:
real    1m22.629s
user    0m31.498s
sys     0m18.899s
postpatch:
real    1m11.465s
user    0m26.382s
sys     0m12.986s

Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
2008-04-17 14:29:08 -05:00

386 lines
12 KiB
Python
Executable File

#! /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, see <http://www.gnu.org/licenses/>.
import os
import tempfile
import shutil
import tarfile
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")
if not os.path.isfile(filename):
print "invalid db entry found (desc missing) for pkg", pkgname
return None
fd = open(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")
if not os.path.isfile(filename):
print "invalid db entry found (files missing) for pkg", pkgname
return None
fd = open(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")
if not os.path.isfile(filename):
print "invalid db entry found (depends missing) for pkg", pkgname
return None
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 == "%OPTDEPENDS%":
pkg.optdepends = _getsection(fd)
elif line == "%CONFLICTS%":
pkg.conflicts = _getsection(fd)
elif line == "%PROVIDES%":
pkg.provides = _getsection(fd)
# TODO this was going to be changed, but isn't anymore
#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):
"""
"""
if self.treename == "local":
path = os.path.join(self.dbdir, self.treename, pkg.fullname())
else:
path = os.path.join(self.dbdir, "sync", self.treename, pkg.fullname())
mkdir(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 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.packager:
data.append(_mksection("PACKAGER", pkg.packager))
if self.treename == "local":
if pkg.url:
data.append(_mksection("URL", pkg.url))
if pkg.installdate:
data.append(_mksection("INSTALLDATE", pkg.installdate))
if pkg.size:
data.append(_mksection("SIZE", pkg.size))
if pkg.reason:
data.append(_mksection("REASON", pkg.reason))
else:
data.append(_mksection("FILENAME", pkg.filename()))
if pkg.replaces:
data.append(_mksection("REPLACES", pkg.replaces))
if pkg.force:
data.append(_mksection("FORCE", ""))
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, conflicts, provides
# for sync ones: depends, conflicts, provides
data = []
if pkg.depends:
data.append(_mksection("DEPENDS", pkg.depends))
if pkg.optdepends:
data.append(_mksection("OPTDEPENDS", pkg.optdepends))
if pkg.conflicts:
data.append(_mksection("CONFLICTS", pkg.conflicts))
if pkg.provides:
data.append(_mksection("PROVIDES", pkg.provides))
#if 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
mkdir(path)
archive = os.path.join(path, "%s%s" % (self.treename, PM_EXT_DB))
tar = tarfile.open(archive, "w:gz")
for root, dirs, files in os.walk('.'):
for d in dirs:
tar.add(os.path.join(root, d), recursive=False)
for f in files:
tar.add(os.path.join(root, f))
tar.close()
os.chdir(curdir)
shutil.rmtree(tmpdir)
def ispkgmodified(self, pkg):
"""
"""
modified = 0
oldpkg = self.getpkg(pkg.name)
if not oldpkg:
return 0
vprint("\toldpkg.checksum : %s" % oldpkg.checksum)
vprint("\toldpkg.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 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: