--- /dev/null
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2007, 2008, 2009 Michael Tremer & Christian Schmidt #
+# #
+# 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 3 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/>. #
+# #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+PKG_NAME = pakfire
+PKG_VER = 0.9
+PKG_REL = 0
+
+THISAPP = $(PKG_NAME)-$(PKG_VER)
+DIR_APP = $(DIR_SOURCE)/$(PKG_NAME)
+
+OBJECT = $(DIR_INFO)/$(STAGE_ORDER)_$(STAGE)/$(THISAPP)
+
+MAINTAINER = Michael Tremer <michael.tremer@ipfire.org>
+GROUP = System/Packaging
+CORE = yes
+EXTRA = no
+DEBUG = no
+BUILD_DEPS =
+DEPS = cpio xz python python-sqlite2 python-urlgrabber system-release
+
+URL = http://www.ipfire.org/
+LICENSE = GPLv3+
+SHORT_DESC = Package installer/updater.
+
+define LONG_DESC
+ Pakfire optains package lists from the mirrors and can install and update \
+ packages.
+endef
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects =
+
+download: $(objects)
+
+info:
+ $(DO_PKG_INFO)
+
+install: $(OBJECT)
+
+package:
+ @$(DO_PACKAGE)
+
+$(objects):
+ @$(LOAD)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(OBJECT): $(objects)
+ @$(PREBUILD)
+ cd $(DIR_APP) && make VERSION="$(PKG_VER)" $(PARALLELISMFLAGS)
+ cd $(DIR_APP) && make install
+ cd $(DIR_APP) && make clean
+ $(PYTHON_COMPILE)
+ @$(POSTBUILD)
ipfire_make nss_ldap
ipfire_make ldapvi
ipfire_make sqlite
+ ipfire_make python-sqlite2
ipfire_make curl
ipfire_make pinentry
ipfire_make gnupg2
ipfire_make pyfire
ipfire_make network
ipfire_make firewall
+ ipfire_make pakfire
}
################################################################################
--- /dev/null
+
+SUBSTITUDE = sed -e "s/@VERSION@/$(VERSION)/g"
+
+PYTHON_MAJ = "2.6"
+PYTHON_DIR = $(DESTDIR)/usr/lib/python$(PYTHON_MAJ)/site-packages/pakfire
+
+all: pakfire
+
+pakfire: pakfire.in
+ $(SUBSTITUDE) pakfire.in > pakfire
+
+clean:
+ rm -vf pakfire python/*.py[co]
+
+install: pakfire
+ install -v -m 755 pakfire $(DESTDIR)/usr/bin
+ -mkdir -pv $(PYTHON_DIR)
+ cp -vf python/*.py $(PYTHON_DIR)/
+ -mkdir -pv $(DESTDIR)/etc/pakfire.repos.d $(DESTDIR)/var/cache/pakfire
--- /dev/null
+#!/bin/bash
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2007, 2008, 2009 Michael Tremer & Christian Schmidt #
+# #
+# 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 3 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/>. #
+# #
+###############################################################################
+
+function pkg_get_file() {
+ cpio --extract --quiet --to-stdout $1 < $2
+}
+
+function pkg_info() {
+ pkg_get_file info $1
+}
+
+function pkg_data() {
+ pkg_get_file data.img $1
+}
+
+function pkg_control() {
+ pkg_get_file control $1
+}
+
+function pkg_verify() {
+ local pak=$1
+ (
+ eval $(pkg_info $pak | grep ^PKG_DATA_SHA1)
+ if [ "$(pkg_data $pak | sha1sum | awk '{ print $1 }')" = "$PKG_DATA_SHA1" ]; then
+ exit 0
+ else
+ exit 1
+ fi
+ )
+ return $?
+}
--- /dev/null
+#!/usr/bin/python
+
+import sys
+
+from optparse import OptionParser
+
+import pakfire
+from pakfire.package import Package
+from pakfire.transactionset import Transactionset
+
+__version__ = "@VERSION@"
+
+op = OptionParser(usage="%prog [options] <action> ...", version="%prog " + __version__)
+op.add_option("-r", "--root", dest="root", metavar="DIR")
+op.add_option("-v", "--verbose", dest="verbose",
+ action="store_true", default=False,
+ help="Be verbose.")
+op.add_option("-y", "--yes", dest="allyes",
+ action="store_true", default=False,
+ help="Answer all questions with \"yes\".")
+op.add_option("--nogpgcheck", dest="gpgcheck",
+ action="store_false", default=True,
+ help="Omit gpg check (unsafe).")
+
+def usage(exit=1):
+ op.print_help()
+ sys.exit(exit)
+
+def parse_options():
+ (options, args) = op.parse_args()
+
+ # When no command was given
+ if not args:
+ usage()
+
+ # The first argument is the action
+ action = args.pop(0)
+ if not action in ["install", "remove", "info", "provides",]:
+ op.error("\"%s\" is not a valid action." % action)
+
+ if not args:
+ op.error("Action \"%s\" needs at least one argument.")
+
+ return (action, options, args)
+
+(action, options, args) = parse_options()
+
+pakfire = pakfire.Pakfire()
+
+if action == "install":
+ pakfire.ts = Transactionset()
+ for a in args:
+ p = Package(a)
+ pakfire.ts.addPackage(p)
+
+ pakfire.ts.run()
+
+elif action == "info":
+ for a in args:
+ p = Package(a)
+ print p.print_info()
--- /dev/null
+#!/usr/bin/python
+
+from repo import Repositories
+from transactionset import Transactionset
+
+class Pakfire(object):
+ repos = Repositories()
+ ts = Transactionset()
+
+ def __init__(self):
+ pass
--- /dev/null
+
+
+from pysqlite2 import dbapi2 as sqlite
+
+DATABASE_PATH = "."
+
+class Database(object):
+ def __init__(self, filename):
+ self.filename = filename
+
+ self.connection = sqlite.connect(self.filename)
+
+ def add(self, table):
+ c = self.cursor
+ c.executescript("CREATE TABLE IF NOT EXISTS %s(id, key, value);" % table)
+ c.close()
+
+ def commit(self):
+ self.connection.commit()
+
+ def destroy(self, table):
+ c = self.cursor
+ c.execute("DELETE FROM %s" % table)
+ c.close()
+ self.commit()
+
+ def get(self, table, id, key):
+ ret = None
+ c = self.cursor
+ c.execute("SELECT value FROM %s WHERE id='%s' AND key='%s';" % \
+ (table, id, key,))
+ try:
+ ret = c.fetchone()[0]
+ except TypeError:
+ pass
+ c.close()
+ return ret
+
+ def set(self, table, id, key, value):
+ c = self.cursor
+ if not self.get(id, key):
+ c.execute("INSERT INTO %s(id, key, value) VALUES('%s', '%s', '%s');" \
+ % (table, id, key, value,))
+ else:
+ c.execute("UPDATE %s SET value='%s' WHERE id='%s' AND key='%s';" \
+ % (table, value, id, key,))
+ c.close()
+ self.commit()
+
+ @property
+ def cursor(self):
+ return self.connection.cursor()
--- /dev/null
+#!/usr/bin/python
+
+import grp
+import os
+import pwd
+import stat
+import time
+
+def ftype(mode):
+ if stat.S_ISBLK(mode):
+ return "b"
+ elif stat.S_ISCHR(mode):
+ return "c"
+ elif stat.S_ISDIR(mode):
+ return "d"
+ elif stat.S_ISREG(mode):
+ return "-"
+ elif stat.S_ISFIFO(mode):
+ return "p"
+ elif stat.S_ISLINK(mode):
+ return "l"
+ elif stat.S_ISSOCK(mode):
+ return "s"
+ return "?"
+
+def rwx(mode):
+ ret = ""
+ if mode & stat.S_IRUSR:
+ ret += "r"
+ else:
+ ret += "-"
+
+ if mode & stat.S_IWUSR:
+ ret += "w"
+ else:
+ ret += "-"
+
+ if mode & stat.S_IXUSR:
+ ret += "x"
+ else:
+ ret += "-"
+
+ return ret
+
+def fmode(mode):
+ ret = ftype(mode)
+ ret += rwx((mode & 0700) << 0)
+ ret += rwx((mode & 0070) << 3)
+ ret += rwx((mode & 0007) << 6)
+ return ret
+
+class CpioError(Exception):
+ pass
+
+
+class CpioEntry(object):
+ def __init__(self, hdr, archive, offset):
+ self.archive = archive
+ self.hdr = hdr
+
+ self.offset = offset + 110 + self.namesize
+ self.offset += (4 - (self.offset % 4)) % 4
+ self.current = 0
+
+ self.closed = False
+
+ if len(self.hdr) < 110:
+ raise CpioError("Header too short.")
+
+ if not self.hdr.startswith("070701") and not self.hdr.startswith("070702"):
+ raise CpioError("Invalid header: %s" % self.hdr[:6])
+
+ def close(self):
+ self.closed = True
+
+ def flush(self):
+ pass # noop
+
+ def read(self, size=None):
+ """Read data from the entry.
+
+ Keyword arguments:
+ size -- Number of bytes to read (default: whole entry)
+ """
+ if self.closed:
+ raise ValueError("Read operation on closed file.")
+
+ self.archive.file.seek(self.offset + self.current, os.SEEK_SET)
+
+ if size and size < self.size - self.current:
+ ret = self.archive.file.read(size)
+ else:
+ ret = self.archive.file.read(self.size - self.current)
+ self.current += len(ret)
+ return ret
+
+ def seek(self, offset, whence=0):
+ """Move to new position within an entry.
+
+ Keyword arguments:
+ offset -- Byte count
+ whence -- Describes how offset is used.
+ 0: From beginning of file
+ 1: Forwards from current position
+ 2: Backwards from current position
+ Other values are ignored.
+ """
+ if self.closed:
+ raise ValueError("Seek operation on closed file.")
+
+ if whence == os.SEEK_SET:
+ self.current = offset
+ elif whence == os.SEEK_REL:
+ self.current += offset
+ elif whence == os.SEEK_END:
+ self.current -= offset
+
+ self.current = min(max(0, self.current), self.size)
+
+ def tell(self):
+ """Get current position within an entry"""
+ if self.closed:
+ raise ValueError("Tell operation on closed file.")
+ return self.current
+
+ def __repr__(self):
+ return "<CpioEntry %s 0x%s>" % (self.name, self.checksum,)
+
+ @property
+ def checksum(self):
+ return int(self.hdr[102:110], 16)
+
+ @property
+ def devmajor(self):
+ return int(self.hdr[62:70], 16)
+
+ @property
+ def devminor(self):
+ return int(self.hdr[70:78], 16)
+
+ @property
+ def gid(self):
+ return int(self.hdr[30:38], 16)
+
+ @property
+ def inode(self):
+ return int(self.hdr[6:14], 16)
+
+ @property
+ def mode(self):
+ return int(self.hdr[14:22], 16)
+
+ @property
+ def mtime(self):
+ return int(self.hdr[46:54], 16)
+
+ @property
+ def name(self):
+ end = 110 + self.namesize - 1
+ return self.hdr[110:end]
+
+ @property
+ def namesize(self):
+ return int(self.hdr[94:102], 16)
+
+ @property
+ def nlinks(self):
+ return int(self.hdr[38:46], 16)
+
+ @property
+ def rdevmajor(self):
+ return int(self.hdr[78:86], 16)
+
+ @property
+ def rdevminor(self):
+ return int(self.hdr[86:94], 16)
+
+ @property
+ def size(self):
+ return int(self.hdr[54:62], 16)
+
+ @property
+ def uid(self):
+ return int(self.hdr[22:30], 16)
+
+
+class CpioArchive(object):
+ _entries = []
+ file = None
+
+ def __init__(self, filename):
+
+ self.filename = filename
+ self.file = open(self.filename, "r")
+ self.__readfile()
+
+ self.closed = False
+
+ def close(self):
+ if self.closed:
+ return
+ self.closed = True
+
+ self.file.close()
+
+ def __readfile(self):
+ if not self.file:
+ raise CpioError("File was not yet opened.")
+
+ self._entries = []
+ sposition = self.file.tell()
+ hdr = self.file.read(110)
+ while hdr:
+ namelen = int(hdr[94:102], 16) # Length of the name
+ hdr += self.file.read(namelen)
+ ce = CpioEntry(hdr, self, sposition)
+ if ce.name == "TRAILER!!!":
+ return
+ self._entries.append(ce)
+
+ self.file.seek((4 - (self.file.tell()-sposition) % 4) % 4, os.SEEK_CUR)
+ self.file.seek(ce.size, os.SEEK_CUR)
+ self.file.seek((4 - (self.file.tell()-sposition) % 4) % 4, os.SEEK_CUR)
+
+ sposition = self.file.tell()
+ hdr = self.file.read(110)
+ else:
+ raise CpioError("Premature end of headers.")
+
+ @property
+ def entries(self):
+ return sorted(self._entries)
+
+ @property
+ def size(self):
+ return os.path.getsize(self.filename)
+
+ def ls(self):
+ for x in self.entries:
+ print x.name
+
+ def ll(self):
+ for x in self.entries:
+ print "%s %s %s %s %9d %s %s" % \
+ (fmode(x.mode),
+ x.nlinks,
+ pwd.getpwuid(x.uid)[0],
+ grp.getgrgid(x.gid)[0],
+ x.size,
+ time.strftime("%Y-%m-%d %H:%M", time.localtime(x.mtime)),
+ x.name,)
+
+ def get(self, item):
+ for x in self.entries:
+ if x.name == item:
+ return x
+ raise KeyError("No such file or directory.")
+
+ def __getitem__(self, item):
+ x = self.get(item)
+ x.seek(0)
+ return x.read()
--- /dev/null
+#!/usr/bin/python
+
+import hashlib
+import os
+import subprocess
+
+import io
+
+class Package(object):
+ _info = {}
+
+ def __init__(self, archive):
+ self.archive = io.CpioArchive(archive)
+
+ def check(self):
+ print "Checking package %s..." % self.name
+ return self.verify()
+
+ def extract(self, root="/"):
+ if not os.path.exists(root):
+ os.makedirs(root)
+
+ lzma = subprocess.Popen(["lzma", "-dc"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,)
+
+ cpio = subprocess.Popen(["cpio",
+ "--quiet",
+ "--extract",
+ "--unconditional",
+ "--make-directories",
+ "--no-absolute-filenames",],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=root)
+
+ BUF = 1024
+ file = self.archive["data.img"]
+
+ # Decompress in one big swoop.
+ lzma.stdin.write(file)
+ lzma.stdin.close()
+
+ lzmaerr = lzma.stderr.read()
+ if lzmaerr:
+ raise Exception("Decompression error: %s" % lzmaerr)
+
+ while True:
+ buf = lzma.stdout.read(BUF)
+ if not buf:
+ break
+ cpio.stdin.write(buf)
+ lzma.stdout.close()
+
+ cpioerr = cpio.stderr.read()
+ if cpioerr:
+ raise Exception("Archiving error: %s" % cpioerr)
+
+ def install(self, root="/"):
+ print "Installing %s..." % self.name
+ self.extract(root)
+
+ def print_info(self):
+ ret = ""
+ info = (("Name", self.name),
+ ("Version", self.version),
+ ("Arch", self.arch),
+ ("Release", self.release),
+ ("Size", self.size),
+ ("Summary", self.summary),
+ ("URL", self.url),
+ ("License", self.license),
+ ("Description", self.description))
+
+ for (key, value) in info:
+ ret += "%-12s: %s\n" % (key, value,)
+
+ if self.verify:
+ ret += "%-12s: %s\n" % ("Signature", "OK")
+ else:
+ ret += "%-12s: %s\n" % ("Signature", "Broken")
+
+ return ret
+
+ def verify(self):
+ hash = hashlib.sha1(self.archive["data.img"]).hexdigest()
+ if hash == self.sha1:
+ return True
+ return False
+
+ @property
+ def arch(self):
+ return self.info.get("PKG_ARCH", None)
+
+ @property
+ def deps(self):
+ return self.info.get("PKG_DEPS", None)
+
+ @property
+ def description(self):
+ return self.info.get("PKG_DESC", None)
+
+ @property
+ def group(self):
+ return self.info.get("PKG_GROUP", None)
+
+ @property
+ def license(self):
+ return self.info.get("PKG_LICENSE", None)
+
+ @property
+ def name(self):
+ return self.info.get("PKG_NAME", None)
+
+ @property
+ def info(self):
+ if not self._info:
+ self._info = {}
+ for line in self.archive["info"].split("\n"):
+ if not line or line.startswith("#"):
+ continue
+ (key, value) = line.split("=")
+ self._info[key] = value.strip("\"")
+ return self._info
+
+ @property
+ def release(self):
+ return self.info.get("PKG_REL", None)
+
+ @property
+ def sha1(self):
+ return self.info.get("PKG_DATA_SHA1", None)
+
+ @property
+ def size(self):
+ return self.archive.size
+
+ @property
+ def summary(self):
+ return self.info.get("PKG_SUMMARY", None)
+
+ @property
+ def url(self):
+ return self.info.get("PKG_URL", None)
+
+ @property
+ def version(self):
+ return self.info.get("PKG_VER", None)
+
--- /dev/null
+
+import os
+import ConfigParser as configparser
+import urlgrabber
+
+import db as database
+from servers import Servers
+
+REPOS_PATH = "/etc/pakfire.repos.d"
+
+class Repositories(object):
+ _repositories = []
+
+ def __init__(self):
+ for file in os.listdir(REPOS_PATH):
+ if not file.endswith(".repo"):
+ continue
+ cp = configparser.ConfigParser()
+ cp.read(os.path.join(REPOS_PATH, file))
+ for section in cp.sections():
+ self._repositories.append(Repository(section, cp.items(section)))
+
+ @property
+ def all(self):
+ return sorted(self._repositories)
+
+ @property
+ def enabled(self):
+ ret = []
+ for r in self._repositories:
+ if r.enabled:
+ ret.append(r)
+ return ret
+
+ @property
+ def repositories(self):
+ return self.enabled
+
+class Repository(object):
+ def __init__(self, name, items=None):
+ self.name = name
+
+ if items:
+ config = {}
+ for (key, value) in items:
+ config[key] = value
+ self.config = config
+
+ self.db = database.Database("%s.db" % self.name)
+ self.servers = Servers(self.db)
+
+ def __cmp__(self, other):
+ return cmp(self.name, other.name)
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return "<Repository %s>" % self.name
+
+ def update_mirrorlist(self, mirrorlist=None):
+ if not mirrorlist:
+ mirrorlist = self.mirrorlist
+ f = urlgrabber.urlopen(mirrorlist)
+ for line in f.readlines():
+ self.servers.add(line)
+ f.close()
+
+ @property
+ def enabled(self):
+ value = self.config.get("enabled")
+ if value == "1":
+ return True
+ return False
+
+ @property
+ def gpgkey(self):
+ return self.config.get("gpgkey", None)
+
+ @property
+ def mirrorlist(self):
+ return self.config.get("mirrorlist", None)
+
+
+if __name__ == "__main__":
+ rs = Repositories()
+ for r in rs.repositories:
+ r.update_mirrorlist()
--- /dev/null
+
+import random
+import urlparse
+import uuid
+
+SERVER_DEFAULT_PROTOCOL = "http"
+SERVER_DEFAULT_PORT = "80"
+SERVER_DEFAULT_PATH = ""
+
+class Servers(object):
+ table = "servers"
+
+ def __init__(self, db):
+ self.db = db
+ self.db.add(self.table)
+
+ def add(self, url):
+ p = urlparse.urlparse(url)
+ for server in self.all:
+ if str(server) == url:
+ return
+ server = Server(self.db)
+ (server.protocol, server.hostname, server.port, server.path) = \
+ (p.scheme, p.hostname, p.port, p.path)
+
+ @property
+ def all(self):
+ ret = []
+ c = self.db.cursor
+ c.execute("SELECT DISTINCT id FROM %s" % self.table)
+ for id in c.fetchall():
+ s = Server(self.db, id)
+ ret.append(s)
+ return sorted(ret)
+
+ @property
+ def random(self):
+ return random.choice(self.all)
+
+
+class Server(object):
+ table = Servers.table
+
+ def __init__(self, db, id=None):
+ self.db = db
+
+ if not id:
+ id = str(uuid.uuid4())
+ self.id = "%s" % id
+
+ def __str__(self):
+ return urlparse.urlunparse((self.protocol, \
+ "%s:%s" % (self.hostname, self.port), self.path, None, None, None))
+
+ def __repr__(self):
+ return "<Server %s>" % self.id
+
+ def _getHostname(self):
+ return self.db.get(self.table, self.id, "hostname")
+
+ def _setHostname(self, hostname):
+ return self.db.set(self.table, self.id, "hostname", hostname)
+
+ hostname = property(_getHostname, _setHostname)
+
+ def _getProtocol(self):
+ return self.db.get(self.table, self.id, "protocol") or SERVER_DEFAULT_PROTOCOL
+
+ def _setProtocol(self, protocol):
+ return self.db.set(self.table, self.id, "protocol", protocol)
+
+ protocol = property(_getProtocol, _setProtocol)
+
+ def _getPort(self):
+ return self.db.get(self.table, self.id, "port") or SERVER_DEFAULT_PORT
+
+ def _setPort(self, port):
+ return self.db.set(self.table, self.id, "port", port)
+
+ port = property(_getPort, _setPort)
+
+ def _getPath(self):
+ return self.db.get(self.table, self.id, "path") or SERVER_DEFAULT_PATH
+
+ def _setPath(self, path):
+ return self.db.set(self.table, self.id, "path", path)
+
+ path = property(_getPath, _setPath)
--- /dev/null
+
+
+class Transactionset(object):
+ _packages = []
+
+ def __init__(self):
+ pass
+
+ def addPackage(self, package):
+ self._packages.append(package)
+
+ def check(self):
+ print "Checking Transactionset..."
+ for package in self.packages:
+ if not package.check():
+ return False
+ return True
+
+ def install(self, root="/"):
+ for package in self.packages:
+ package.install(root)
+
+ def resolveDeps(self):
+ pass
+
+ def run(self, root="/"):
+ print "Running transactionset..."
+ if self.check():
+ self.install(root)
+ else:
+ print "Error, when verifying the packages..."
+
+ @property
+ def packages(self):
+ return sorted(self._packages)
--- /dev/null
+etc/pakfire.repos.d
+usr/bin/pakfire
+usr/lib/python2.6/site-packages/pakfire
+usr/lib/python2.6/site-packages/pakfire/__init__.py
+usr/lib/python2.6/site-packages/pakfire/__init__.pyc
+usr/lib/python2.6/site-packages/pakfire/__init__.pyo
+usr/lib/python2.6/site-packages/pakfire/db.py
+usr/lib/python2.6/site-packages/pakfire/db.pyc
+usr/lib/python2.6/site-packages/pakfire/db.pyo
+usr/lib/python2.6/site-packages/pakfire/io.py
+usr/lib/python2.6/site-packages/pakfire/io.pyc
+usr/lib/python2.6/site-packages/pakfire/io.pyo
+usr/lib/python2.6/site-packages/pakfire/package.py
+usr/lib/python2.6/site-packages/pakfire/package.pyc
+usr/lib/python2.6/site-packages/pakfire/package.pyo
+usr/lib/python2.6/site-packages/pakfire/repo.py
+usr/lib/python2.6/site-packages/pakfire/repo.pyc
+usr/lib/python2.6/site-packages/pakfire/repo.pyo
+usr/lib/python2.6/site-packages/pakfire/servers.py
+usr/lib/python2.6/site-packages/pakfire/servers.pyc
+usr/lib/python2.6/site-packages/pakfire/servers.pyo
+usr/lib/python2.6/site-packages/pakfire/transactionset.py
+usr/lib/python2.6/site-packages/pakfire/transactionset.pyc
+usr/lib/python2.6/site-packages/pakfire/transactionset.pyo
+var/cache/pakfire