diff --git a/src/CODING b/src/CODING deleted file mode 100644 index cc6b0c25..00000000 --- a/src/CODING +++ /dev/null @@ -1,75 +0,0 @@ -Like every serious project, there are guidelines. -Oooooo. "Coding Standards". - -Guidelines ----------- - -1. When using dirnames, don't expect the dir to end - with a trailing slash, and please use the dirnames - in pisiconfig -2. Python indentation is usually 4 chars. -3. Follow python philosophy of 'batteries included' -4. Don't make the code have runtime dependencies on - a particular distribution (as much as possible) -5. Don't assume narrow use cases. -6. If you are changing something, check if that change - breaks anything and fix breakage. For instance a - name. Running the tests is not always enough! - -Unit testing ------------- - -Unit tests are located in unittests directory. Running the tests is -trivial. But you must synchronize your code and data with the test -code, which can be a tedious work if you lose discipline. - -Sample data files are located in samples/ directory. - -For running the entire test suite, use the following command: - -$ ./unittests/run.py - -If you know what you are doing, you can run the tests seperately. But -keep in your mind that tests can depend on each other. (?) The unit test -system doesn't know about that. The following command will run tests -in specfiletests and archivetests in unittests dir: - -$ ./unittests/run.py specfile archive - - -Misc. Suggestions ------------------ - -1. Demeter's Law - -In OO programming, try to invoke Demeter's law. -One of the "rules" there is not directly accessing any -objects that are further than, 2/3 refs, away. So the -following code is OK. - destroy_system(a.system().name()) -but the following isn't as robust - destroy_system(object_store.root().a.system.name()) -As you can tell, this introduces too many implementation -dependencies. The rule of thumb is that, in these cases -this statement must have been elsewhere.... It may be a -good idea to not count the object scope in this case, -so in Python self.a means only one level of reference, -not two. - -One quibble with this: it may be preferable not to insist -on this where it would be inefficient. So if everything -is neatly packed into one object contained in another -object, why replicate everything in the upper level? If -the semantics prevents dependency changes, then chains -of 3 or even 4 could be acceptable. - -OTOH, in Python and C++, it's not always good to implement -accessor/modifier pairs for every property of an object. -It would be much simpler if you are not doing any special -processing on the property (e.g. if what the type system -does is sufficient). - -The main rule of thumb in Demeter's Law is avoiding -putting more than, say, 10 methods in a class. That works -really well in practice, forcing refactoring every now -and then. diff --git a/src/README b/src/README deleted file mode 100644 index 3c05f619..00000000 --- a/src/README +++ /dev/null @@ -1 +0,0 @@ -PISI is a new package manager implemented in python. diff --git a/src/TODO b/src/TODO deleted file mode 100644 index 61a47d4b..00000000 --- a/src/TODO +++ /dev/null @@ -1,23 +0,0 @@ - -PiSi ToDo List -============== - -A list of tasks to accomplish, organized into priority sections - -Legend: - -- Todo -? Not determined if/how we have to do -/ In progress -+ Accomplished - -1. Pre-Alpha - - + implement reading spec file - / implement install database - ? transaction/locking for database - -2. Alpha - -3. Beta - diff --git a/src/pisi-build b/src/pisi-build deleted file mode 100755 index cc8cefa9..00000000 --- a/src/pisi-build +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# python standard library -from os.path import basename - -import pisi.context -import pisi.util -import pisi.ui -from pisi.build import PisiBuild, PisiBuildError - -def usage(progname = "pisi-build"): - print """ -Usage: -%s [options] package-name.pspec -""" %(progname) - -def main(): - import sys - import getopt - - # wrapper for usage(progname) function - help = lambda: usage(sys.argv[0]) - - # getopt magic - try: - opts, args = getopt.getopt(sys.argv[1:],"h",["help"]) - except getopt.GetoptError: - help() - sys.exit(1) - - for opt, arg in opts: - if opt == "-h": - help() - sys.exit(1) - - # pspec(PISI Spec) to be used for package - pspec = "" - - # TODO: We accept only one pspec file (at a time) currently, - # but pisi-build may build many packages (pspecs given in order) - # sequentially. - if len(args) != 1: - help() - raise PisiBuildError, "pisi-build expects one (and only one) pspec file currently" - else: - pspec = args[0] - - # What we need to do first is create a context with our specfile - ctx = pisi.context.Context(pspec) - - # don't do the real job here. this is just a CLI! - pb = PisiBuild(ctx) - pb.build() - - -if __name__ == "__main__": - main() diff --git a/src/pisi-install b/src/pisi-install deleted file mode 100755 index 278a161e..00000000 --- a/src/pisi-install +++ /dev/null @@ -1,43 +0,0 @@ -#! /usr/bin/python -# -*- coding: utf-8 -*- - -# sys modules -import sys -from optparse import OptionParser - -import pisi.install -import pisi.util - -class ArgError(Exception): - pass - -def main(): - - usage = "usage: %prog [options] " - parser = OptionParser(usage=usage,version="%prog " + pisi.__version__) - parser.add_option("-D", "--destdir", action="store") - parser.add_option("-v", "--verbose", action="store_true", - dest="verbose", default=False, - help="detailed output") - parser.add_option("-d", "--debug", action="store_true", default=True) - parser.add_option("-n", "--dry-run", action="store_true", - default = "do not perform any action, just show what\ - would be done") - - (options, args) = parser.parse_args() - - # package filename - package_fn = "" - - # TODO: We accept only one package file arg ATM - if len(args) != 1: - print usage - raise ArgError, "pisi-install expects one (and only one) package file currently" - else: - package_fn = args[0] - - pisi.install.install_package_file(package_fn) - - -if __name__ == "__main__": - main() diff --git a/src/pisi/__init__.py b/src/pisi/__init__.py deleted file mode 100644 index 2816f232..00000000 --- a/src/pisi/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ - -# PISI package version -__version__ = "0.1" - diff --git a/src/pisi/archive.py b/src/pisi/archive.py deleted file mode 100644 index da01c1c1..00000000 --- a/src/pisi/archive.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- -# unpack magic -# maintainer baris and meren - -#standart lisbrary modules -import os -import sys -import tarfile -import zipfile - -#pisi modules -import util - -class ArchiveBase(object): - def __init__(self, ctx): - self.type = ctx.spec.source.archiveType - self.fileName = os.path.basename(ctx.spec.source.archiveUri) - self.filePath = ctx.archives_dir() + '/' + self.fileName - - def unpack(self, targetDir): - self.targetDir = targetDir - # first we check if we need to clean-up our working env. - if os.path.exists(self.targetDir): - util.clean_dir(self.targetDir) - else: - os.makedirs(self.targetDir) - -class ArchiveTarFile(ArchiveBase): - def __init__(self, ctx): - super(ArchiveTarFile, self).__init__(ctx) - - def unpack(self, targetDir): - super(ArchiveTarFile, self).unpack(targetDir) - - rmode = "" - if self.type == 'tar': - rmode = 'r:' - elif self.type == 'targz': - rmode = 'r:gz' - elif self.type == 'tarbz2': - rmode = 'r:bz2' - tar = tarfile.open(self.filePath, rmode) - oldwd = os.getcwd() - os.chdir(self.targetDir) - for tarinfo in tar: - tar.extract(tarinfo) - os.chdir(oldwd) - tar.close() - -class ArchiveZip(ArchiveBase): - def __init__(self, ctx): - super(ArchiveZip, self).__init__(ctx) - - def unpack(self, targetDir): - super(ArchiveZip, self).unpack(targetDir) - - zip = zipfile.ZipFile(self.filePath, 'r') - for file in zip.namelist(): - ofile = self.targetDir + '/' + file - - # a directory is present. lets continue - if os.path.isdir(ofile): - continue - # do we need to create parent directory for our file? - if not os.path.exists(os.path.dirname(ofile)): - os.mkdir(ofile) - continue - info = zip.getinfo(file) - # O.K. we know following line is dull. What we wanted to - # do was to compare the equality to 0xa0000000. But there - # is a known problem in Python regarding the hex/oct - # constants. Please see Guido's explanation at - # http://mail.python.org/pipermail/python-dev/2003-February/033029.html - if hex(info.external_attr)[2] == 'A': - target = zip.read(file) - os.symlink(target, ofile) - else: - buff = open (ofile, 'wb') - fileContent = zip.read(file) - buff.write(fileContent) - buff.close() - - zip.close() - -class Archive: - """Unpack magic for Archive files...""" - - def __init__(self, ctx): - """accepted archive types: - targz, tarbz2, zip, tar""" - - handlers = { - 'targz': ArchiveTarFile, - 'tarbz2': ArchiveTarFile, - 'tar': ArchiveTarFile, - 'zip': ArchiveZip - } - - type = ctx.spec.source.archiveType - self.archive = handlers.get(type)(ctx) - - def unpack(self, targetDir): - self.archive.unpack(targetDir) diff --git a/src/pisi/build.py b/src/pisi/build.py deleted file mode 100644 index db3a150e..00000000 --- a/src/pisi/build.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -# package bulding stuff -# maintainer: baris and meren - -# python standard library -import os - -from fetcher import Fetcher -from archive import Archive - -# import pisipackage -import util -from ui import ui - -class PisiBuildError(Exception): - pass - -# FIXME: this eventually has to go to ui module -# Infact all ui calls has nothing to do with this build process. -# There more of them in PisiBuild... -# And maybe we should consider moving PisiBuild.build() back to pisi-build -# CLI too. -# exa: This, like all others, will have a GUI or CLI, interchangeably -def displayProgress(pd): - out = '\r%-30.30s %3d%% %12.2f %s' % \ - (pd['filename'], pd['percent'], pd['rate'], pd['symbol']) - ui.info(out) - -class PisiBuild: - """PisiBuild class, provides the package build and creation routines""" - def __init__(self, context): - self.ctx = context - self.work_dir = self.ctx.pkg_work_dir() - - self.spec = self.ctx.spec - - def build(self): - ui.info("Building PISI source package: %s\n" % self.spec.source.name) - - ui.info("Fetching source from: %s\n" % self.spec.source.archiveUri) - self.fetchArchive(displayProgress) - ui.info("Source archive is stored: %s/%s\n" - %(self.ctx.archives_dir(), self.spec.source.archiveName)) - - self.solveBuildDependencies() - - ui.info("Unpacking archive...") - self.unpackArchive() - ui.info(" unpacked (%s)\n" % self.ctx.pkg_work_dir()) - - self.applyPatches() - - try: - specdir = os.path.dirname(self.ctx.pspecfile) - self.actionScript = open("/".join([specdir,self.ctx.const.actions_file])).read() - except IOError, e: - ui.error ("Action Script: %s\n" % e) - return - - # FIXME: It's wrong to assume that unpacked archive - # will create a name-version top-level directory. - # Archive module should give the exact location. - # (from the assumption is evil dept.) - os.chdir(self.ctx.pkg_work_dir() + "/" + self.spec.source.name + "-" + self.spec.source.version) - locals = globals = {} - - try: - exec compile(self.actionScript , "error", "exec") in locals,globals - except SyntaxError, e: - ui.error ("Error : %s\n" % e) - return - - self.configureSource(locals) - self.buildSource(locals) - self.installSource(locals) - - # after all, we are ready to build/prepare the packages - self.buildPackages() - - def fetchArchive(self, percentHook=None): - """fetch an archive and store to ctx.archives_dir() - using fether.Fetcher""" - fetch = Fetcher(self.ctx) - - # check if source already cached - destpath = fetch.filedest + "/" + fetch.filename - if os.access(destpath, os.R_OK): - if util.md5_file(destpath) == self.spec.source.archiveMD5: - ui.info('%s [cached]\n' % self.spec.source.archiveName) - return - - if percentHook: - fetch.percentHook = percentHook - - fetch.fetch() - - # FIXME: What a ugly hack! We should really find a cleaner way for output. - if percentHook: - ui.info('\n') - - def solveBuildDependencies(self): - pass - - def unpackArchive(self): - archive = Archive(self.ctx) - archive.unpack(self.work_dir) - - def applyPatches(self): - pass - - def configureSource(self, locals): - func = self.ctx.const.setup_func - if func in locals: - ui.info("Configuring %s...\n" % self.spec.source.name) - locals[func]() - - def buildSource(self, locals): - func = self.ctx.const.build_func - if func in locals: - ui.info("Building %s...\n" % self.spec.source.name) - locals[func]() - - def installSource(self, locals): - func = self.ctx.const.install_func - if func in locals: - ui.info("Installing %s...\n" % self.spec.source.name) - locals[func]() - - def buildPackages(self): - for package in self.spec.packages: - ui.info("** Building package %s\n" % package.name); - diff --git a/src/pisi/colors.py b/src/pisi/colors.py deleted file mode 100644 index 835ddced..00000000 --- a/src/pisi/colors.py +++ /dev/null @@ -1,48 +0,0 @@ - -colors = {'black' : "\033[30m", - 'red' : "\033[31m", - 'green' : "\033[32m", - 'yellow' : "\033[33m", - 'blue' : "\033[34m", - 'purple' : "\033[35m", - 'cyan' : "\033[36m", - 'white' : "\033[37m", - 'brightblack' : "\033[01;30m", - 'brightred' : "\033[01;31m", - 'brightgreen' : "\033[01;32m", - 'brightyellow' : "\033[01;33m", - 'brightblue' : "\033[01;34m", - 'brightmagenta' : "\033[01;35m", - 'brightcyan' : "\033[01;36m", - 'brightwhite' : "\033[01;37m", - 'underlineblack' : "\033[04;30m", - 'underlinered' : "\033[04;31m", - 'underlinegreen' : "\033[04;32m", - 'underlineyellow' : "\033[04;33m", - 'underlineblue' : "\033[04;34m", - 'underlinemagenta' : "\033[04;35m", - 'underlinecyan' : "\033[04;36m", - 'underlinewhite' : "\033[04;37m", - 'blinkingblack' : "\033[05;30m", - 'blinkingred' : "\033[05;31m", - 'blinkinggreen' : "\033[05;32m", - 'blinkingyellow' : "\033[05;33m", - 'blinkingblue' : "\033[05;34m", - 'blinkingmagenta' : "\033[05;35m", - 'blinkingcyan' : "\033[05;36m", - 'blinkingwhite' : "\033[05;37m", - 'backgroundblack' : "\033[07;30m", - 'backgroundred' : "\033[07;31m", - 'backgroundgreen' : "\033[07;32m", - 'backgroundyellow' : "\033[07;33m", - 'backgroundblue' : "\033[07;34m", - 'backgroundmagenta' : "\033[07;35m", - 'backgroundcyan' : "\033[07;36m", - 'backgroundwhite' : "\033[07;37m", - 'default' : "\033[0m" } - -def colorize(msg, color): - if colors.has_key(color): - return colors[color] + msg + colors['default'] - else: - return msg diff --git a/src/pisi/context.py b/src/pisi/context.py deleted file mode 100644 index f95c4e92..00000000 --- a/src/pisi/context.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- -# PISI configuration (static and dynamic) - -from specfile import SpecFile -import oo - -class Constants: - "Pisi constants" - - c = oo.const() - - def __init__(self): - self.c.lib_dir_suffix = "/var/lib/pisi" - self.c.db_dir_suffix = "/var/db/pisi" - self.c.archives_dir_suffix = "/var/cache/pisi/archives" - self.c.tmp_dir_suffix = "/var/tmp/pisi" - - # directory suffixes for build - self.c.work_dir_suffix = "/work" - self.c.install_dir_suffix = "/install" - - # file/directory names - self.c.actions_file = "actions.py" - self.c.files_dir = "files" - - # functions in actions_file - self.c.setup_func = "setup" - self.c.build_func = "build" - self.c.install_func = "install" - - def __getattr__(self, attr): - return getattr(self.c, attr) - - def __setattr__(self, attr, value): - return setattr(self.c, attr, value) - - def __delattr__(self, attr): - return delattr(self.c, attr) - -class Context(object): - """Config/Context Singleton""" - class __impl: - def __init__(self): - self.const = Constants() - # self.c.destdir = '' # install default to root by default - self.destdir = './tmp' # only for ALPHA - # the idea is that destdir can be set with --destdir=... - - def setSpecFile(self, pspecfile): - self.pspecfile = pspecfile - spec = SpecFile() - spec.read(pspecfile) - spec.verify() # check pspec integrity - self.spec = spec - - # directory accessor functions - # here is how it goes - # x_dir: system wide directory for storing info type x - # pkg_x_dir: per package directory for storing info type x - - def lib_dir(self): - return self.destdir + self.const.lib_dir_suffix - - def db_dir(self): - return self.destdir + self.const.db_dir_suffix - - def archives_dir(self): - return self.destdir + self.const.archives_dir_suffix - - def tmp_dir(self): - return self.destdir + self.const.tmp_dir_suffix - - def pkg_work_dir(self): - packageDir = self.spec.source.name + '-' \ - + self.spec.source.version + '-' + self.spec.source.release - - return self.destdir + self.const.tmp_dir_suffix \ - + '/' + packageDir + self.const.work_dir_suffix - - def install_dir(self): - return self.tmp_dir() + self.const.install_dir_suffix - - def pkg_install_dir(self): - packageDir = self.spec.source.name + '-' \ - + self.spec.source.version + '-' + self.spec.source.release - - return self.destdir + self.const.tmp_dir_suffix \ - + '/' + packageDir + self.const.install_dir_suffix - - __instance = __impl() - - def __init__(self, pspecfile = None): - if pspecfile != None: - self.__instance.setSpecFile(pspecfile) - - def __getattr__(self, attr): - return getattr(self.__instance, attr) - - def __setattr__(self, attr, value): - return setattr(self.__instance, attr, value) - - -# create a default context WITH NO PSPEC -ctx = Context() diff --git a/src/pisi/dependency.py b/src/pisi/dependency.py deleted file mode 100644 index 9f1379f8..00000000 --- a/src/pisi/dependency.py +++ /dev/null @@ -1,3 +0,0 @@ -# dependency analyzer -# maintainer: eray and caglar - diff --git a/src/pisi/fetcher.py b/src/pisi/fetcher.py deleted file mode 100644 index 79651ff6..00000000 --- a/src/pisi/fetcher.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -# download magic -# maintainer: baris and meren - -# python standard library modules -import urlparse -import urllib2 -import os - -# pisi modules -import util - -class FetchError (Exception): - pass - -class Fetcher: - """Yet another Pisi tool for fetching files from various sources..""" - def __init__(self, ctx): - self.uri = ctx.spec.source.archiveUri - self.filedest = ctx.archives_dir() - util.check_dir(self.filedest) - self.scheme = "file" - self.netloc = "" - self.filepath = "" - self.filename = "" - self.percent = 0 - self.rate = 0.0 - self.percentHook = None - from string import split - u = urlparse.urlparse(self.uri) - self.scheme, self.netloc, self.filepath = u[0], u[1], u[2] - self.filename = os.path.basename(self.uri) - - def fetch (self): - """Return value: Fetched file's full path..""" - - if self.filename == "": - self.err("filename error") - - if os.access(self.filedest, os.W_OK) == False: - self.err("no perm to write to dest dir") - - scheme_err = lambda: self.err("unexpected scheme") - - handlers = { - 'file': self.fetchLocalFile, - 'http': self.fetchRemoteFile, - 'ftp' : self.fetchRemoteFile - }; handlers.get(self.scheme, scheme_err)() - - return self.filedest + "/" + self.filename - - def doGrab(self, file, dest, totalsize): - symbols = [' B/s', 'KB/s', 'MB/s', 'GB/s'] - from time import time - tt, oldsize = int(time()), 0 - p = Progress(totalsize) - bs, size = 1024, 0 - symbol, depth = "B/s", 0 - st = time() - chunk = file.read(bs) - size = size + len(chunk) - self.percent = p.update(size) - while chunk: - dest.write(chunk) - chunk = file.read(bs) - size = size + len(chunk) - ct = time() - if int(tt) != int(ct): - self.rate = size / (ct - st) - while self.rate > 1000 and depth < 3: - self.rate /= 1024 - depth += 1 - symbol, depth = symbols[depth], 0 - oldsize, tt = size, time() - if p.update(size): - self.percent = p.percent - if self.percentHook != None: - retval = {'filename': self.filename, - 'percent' : self.percent, - 'rate': self.rate, - 'symbol': symbol} - self.percentHook(retval) - - dest.close() - - - def fetchLocalFile (self): - from shutil import copyfile - - if os.access(self.filepath, os.F_OK) == False: - self.err("no such file or no perm to read") - - dest = open(self.filedest + "/" + self.filename , "w") - totalsize = os.path.getsize(self.filepath) - file = open(self.filepath) - self.doGrab(file, dest, totalsize) - - - def fetchRemoteFile (self): - from httplib import HTTPException - - try: - file = urllib2.urlopen(self.uri) - headers = file.info() - - except ValueError, e: - self.err('%s' % (e, )) - except IOError, e: - self.err('%s' % (e, )) - except OSError, e: - self.err('%s' % (e, )) - except HTTPException, e: - self.err(('(%s): %s') % (e.__class__.__name__, e)) - - if not headers is None and not headers.has_key('Content-Length'): - self.err('file not found') - else: totalsize = int(headers['Content-Length']) - - dest = open(self.filedest + "/" + self.filename , "w") - self.doGrab(file, dest, totalsize) - - - def err (self, error): - raise FetchError(error) - -class Progress: - def __init__(self, totalsize): - self.totalsize = totalsize - self.percent = 0 - - def update(self, size): - percent = (size * 100) / self.totalsize - if percent and self.percent is not percent: - self.percent = percent - return percent - else: - return 0 - diff --git a/src/pisi/install.py b/src/pisi/install.py deleted file mode 100644 index fe98d925..00000000 --- a/src/pisi/install.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -#import package -from specfile import * -from package import Package -import util -from context import ctx -from ui import ui -import installdb -import packagedb -import dependency -#import conflicts - -class InstallError(Exception): - pass - -def install_package_file(package_fn): - - package = Package(package_fn, 'r') - # extract control files - util.clean_dir(ctx.install_dir()) - ui.info('extracting files\n') - package.extract_PISI_files(ctx.install_dir()) - - # verify package - # check if we have all required files - - metadata = MetaData() - metadata.read(ctx.install_dir() + '/metadata.xml') - # check package semantics - if not metadata.verify(): - raise InstallError("MetaData format wrong") - - # check file system requirements - # what to do if / is split into /usr, /var, etc.? - - # check conflicts - # check dependencies - - # unzip package in place - - # update databases - - # installdb - installdb.install(spec.spec.install_dir() + '/files.xml') - diff --git a/src/pisi/installdb.py b/src/pisi/installdb.py deleted file mode 100644 index 674af9b6..00000000 --- a/src/pisi/installdb.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# installation database -# maintainer: eray and caglar - -import os -import bsddb.dbshelve as shelve - -from context import ctx -import util - -util.check_dir(ctx.db_dir()) -d = shelve.open(ctx.db_dir() + '/install.bdb') -files_dir = ctx.archives_dir() + "/files" - -class InstallDBError(Exception): - pass - -def files_name(name, version, release): - return files_dir + '/' + name + '-' + version + '-' + release - -def files(n, v, r): - return file(files_name(n,v,r)) - -def is_recorded(name, version, release): - key = name + version + release - return d.has_key(key) - -def is_installed(name, version, release): - key = name + version + release - return is_recorded(name,version,release) and d[key]=='i' - -def is_removed(name, version, release): - key = name + version + release - return is_recorded(name,version,release) and d[key]=='r' - -def install(name, version, release, files_xml): - key = name + version + release - if is_installed(name, version, release): - raise InstallDBError("already installed") - d[key] = 'i' - util.copy_file(files_xml, files_name(name, version, release)) - -def remove(name, version, release): - key = name + version + release - d[key] = 'r' - -def purge(name, version, release): - os.unlink(files_name(name, version, release)) - key = name + version + release - del d[key] - - diff --git a/src/pisi/oo.py b/src/pisi/oo.py deleted file mode 100644 index 4cbbd866..00000000 --- a/src/pisi/oo.py +++ /dev/null @@ -1,20 +0,0 @@ -# OO extensions -# thes are really cool, you can't do this in C++ :) - -class const: - "Constant members implementation" - class ConstError(TypeError): - pass - - def __setattr__(self, name, value): - if self.__dict__.has_key(name): - raise self.ConstError, "Can't rebind constant: %s" % name - # Binding an attribute once to a const is available - self.__dict__[name] = value - - def __delattr__(self, name): - if self.__dict__.has_key(name): - raise self.ConstError, "Can't unbind constant: %s" % name - # we don't have an attribute by this name - raise NameError, name - diff --git a/src/pisi/package.py b/src/pisi/package.py deleted file mode 100644 index 73e1e9a5..00000000 --- a/src/pisi/package.py +++ /dev/null @@ -1,30 +0,0 @@ -# package abstraction -# provides methods to add/remove files, extract control files -# maintainer: baris and meren - -class Package: - """Package: PISI package class""" - def __init__(self, packagefn, mode): - self.filename = packagefn - self.mode = mode # bu gerekli mi? - # etc. etc. - - def add_file(self, fn): - """add a file to package""" - - def extract(self, outdir): - """extract entire package contents to directory""" - extract_dir('', outdir) # means package root - - def extract_file(self, path, outdir): - """extract file with path to outdir""" - - def extract_dir(self, dir, outdir): - """extract directory recursively""" - - def extract_PISI_files(self, outdir): - """extract PISI control files: metadata.xml, files.xml, - action scripts, etc.""" - self.extract_file('metadata.xml', outdir) - self.extract_file('files.xml', outdir) - self.extract_dir('Config', outdir) diff --git a/src/pisi/packagedb.py b/src/pisi/packagedb.py deleted file mode 100644 index eccc26b1..00000000 --- a/src/pisi/packagedb.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# package database -# interface for update/query to local package repository -# maintainer: eray and caglar - -# we basically store everything in PackageInfo class -# yes, we are cheap - -import bsddb.dbshelve as shelve - -import util -from context import ctx - -util.check_dir(ctx.db_dir()) -d = shelve.open(ctx.db_dir() + '/package.bdb') - -def has_package(name): - return d.has_key(name) - -def get_package(name): - return d[name] - -def add_package(name, package_info): - d[name] = package_info - -def remove_package(name): - del d[name] - diff --git a/src/pisi/sourcedb.py b/src/pisi/sourcedb.py deleted file mode 100644 index 71af3727..00000000 --- a/src/pisi/sourcedb.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -# package source database -# interface for update/query to local package repository -# maintainer: eray and caglar - -# we basically store everything in sourceinfo class -# yes, we are cheap - -import bsddb.dbshelve as shelve - -util.check_dir(config.db_dir()) -d = shelve.open(config.db_dir() + '/source.bdb') - -def add_source(name, source_info): - d[name] = source_info - -def remove_source(name): - del d[name] diff --git a/src/pisi/specfile.py b/src/pisi/specfile.py deleted file mode 100644 index 9566beca..00000000 --- a/src/pisi/specfile.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- -# read/write PISI source package specification file - -import xml.dom.minidom -from xmlfile import * -from os.path import basename - -class PatchInfo: - def __init__(self, filenm, ctype): - self.filename = filenm - self.compressionType = ctype - - def __init__(self, node): - self.filename = getNodeText(node) - self.compressionType = getNodeAttribute(node, "compressionType") - -class DepInfo: - def __init__(self, node): - self.package = getNodeText(node).strip() - self.versionFrom = getNodeAttribute(node, "versionFrom") - -class HistoryInfo: - def __init__(self, node): - self.date = getNodeText(getNode(node, "Date")) - self.version = getNodeText(getNode(node, "Version")) - self.release = getNodeText(getNode(node, "Release")) - -class PathInfo: - def __init__(self, node): - self.pathname = getNodeText(node) - self.fileType = getNodeAttribute(node, "fileType") - -# a structure to hold source information -class SourceInfo: - pass - -class PackageInfo: - def __init__(self, node): - self.name = getNodeText(getNode(node, "Name")) - self.summary = getNodeText(getNode(node, "Summary")) - self.description = getNodeText(getNode(node, "Description")) - self.category = getNodeText(getNode(node, "Category")) - iDepElts = getAllNodes(node, "InstallDependencies") - self.installDeps = [DepInfo(x) for x in iDepElts] - rtDepElts = getAllNodes(node, "RuntimeDependencies") - self.runtimeDeps = [DepInfo(x) for x in rtDepElts] - self.paths = [PathInfo(x) for x in getAllNodes(node, "Files/Path")] - -class SpecFile(XmlFile): - """A class for reading/writing from/to a PSPEC (PISI SPEC) file.""" - - def __init__(self): - XmlFile.__init__(self,"PSPEC") - - def read(self, filename): - """Read PSPEC file""" - - self.readxml(filename) - - self.source = SourceInfo() - self.source.name = self.getChildText("Source/Name") - archiveNode = self.getNode("Source/Archive") - self.source.archiveUri = getNodeText(archiveNode).strip() - self.source.archiveName = basename(self.source.archiveUri) - self.source.archiveType = getNodeAttribute(archiveNode, "archType") - self.source.archiveMD5 = getNodeAttribute(archiveNode, "md5sum") - patchElts = self.getChildElts("Source/Patches") - if patchElts: - self.source.patches = [PatchInfo(p) for p in patchElts] - - buildDepElts = self.getChildElts("Source/BuildDependencies") - if buildDepElts: - self.source.buildDeps = [DepInfo(d) for d in buildDepElts] - - historyElts = self.getAllNodes("History/Update") - self.source.history = [HistoryInfo(x) for x in historyElts] - - # As we have no Source/Version tag we need to get - # the last version and release information - # from the first child of History/Update. And it works :) - self.source.version = self.source.history[0].version - self.source.release = self.source.history[0].release - - # find all binary packages - packageElts = self.getAllNodes("Package") - self.packages = [PackageInfo(p) for p in packageElts] - - def verify(self): - """Verify PSPEC structures, are they what we want of them?""" - return True - - def write(self, filename): - """Write PSPEC file""" - self.writexml(filename) - -class MetaData(SpecFile): - """This is a superset of the source spec definition""" - - def read(self, filename): - SpecFile.read(filename) - distribution = self.getNodeText("Source/Distribution") - distributionRelease = self.getNodeText("Source/DistributionRelease") - architecture = self.getNodeText("Source/Architecture") - installSize = self.getNodeText("Source/InstallSize") - diff --git a/src/pisi/ui.py b/src/pisi/ui.py deleted file mode 100644 index 163aae35..00000000 --- a/src/pisi/ui.py +++ /dev/null @@ -1,30 +0,0 @@ -# generic user interface - -import sys -from colors import colorize - -def register(_impl): - """ Register a UI implementation""" - ui = _impl - -# default UI implementation -class CLI: - def __init__(self, debuggy = True): - self.showDebug = debuggy - - def info(self, msg): - sys.stdout.write(colorize(msg, 'blue')) - sys.stdout.flush() - - def debug(self, msg): - if showDebug: - sys.stdout.write(msg) - sys.stdout.flush() - - def error(self,msg): - sys.stdout.write(colorize(msg, 'red')) - sys.stdout.flush() - -# default UI is CLI -ui = CLI() - diff --git a/src/pisi/util.py b/src/pisi/util.py deleted file mode 100644 index a26f8c76..00000000 --- a/src/pisi/util.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# misc. utility functions, including process and file utils -# maintainer: eray and caglar and baris and meren! - -import os -import sys -import md5 -from ui import ui - -class FileError(Exception): - pass - -class UtilError(Exception): - pass - -# shorthand to check if a file exists -def check_file(file, mode = os.F_OK): - if not os.access(file, mode): - raise FileError("File " + file + " not found") - -# check if directory exists, and create if it doesn't -# works recursively -# FIXME: could have a better name -def check_dir(dir): - dir = dir.strip().rstrip("/") - if not os.access(dir, os.F_OK): - os.makedirs(dir) - -def clean_dir(top): - """Remove all content of a directory (top)""" - for root, dirs, files in os.walk(top, topdown=False): - for name in files: - os.remove(os.path.join(root, name)) - for name in dirs: - os.rmdir(os.path.join(root, name)) - -def copy_file(s,d): - check_file(s) - check_dir(os.path.dirname(d)) - fs = file(s, 'rb') - fd = file(d, 'wb') - for l in fs: - fd.write(l) - -def copy_dir(): - raise UtilError("not implemented") - -def md5_file(filename): - m = md5.new() - f = file(filename, 'rb') - for l in f: - m.update(l) - return m.hexdigest() - -# run a command non-interactively -def run_batch(cmd): - ui.info('running ' + cmd) - a = os.popen(cmd) - lines = a.readlines() - ret = a.close() - ui.debug('return value ' + ret) - successful = ret == None - if not successful: - ui.error('ERROR: executing command: ' + cmd + '\n' + strlist(lines)) - return (successful,lines) - -# print a list -def strlist(l): - return string.join(map(lambda x: str(x) + ' ', l)) diff --git a/src/pisi/xmlfile.py b/src/pisi/xmlfile.py deleted file mode 100644 index 5dbef393..00000000 --- a/src/pisi/xmlfile.py +++ /dev/null @@ -1,141 +0,0 @@ -# -*- coding: utf-8 -*- -# some helper functions for using minidom - -import xml.dom.minidom as mdom - -class XmlError(Exception): - pass - -# static functions - -def getNodeAttribute(node, attrname): - for i in range(node.attributes.length): - attr = node.attributes.item(i) - if attr.name == attrname: - return attr.childNodes[0].data - -def getNodeText(node): - # get the first child - try: - child = node.childNodes[0] - except IndexError: - return None - except AttributeError: # no node by that name - return None - if child.nodeType == child.TEXT_NODE: - return child.data - else: - raise XmlError("getNodeText: Expected text node, got something else!") - -def getChildText(node_s, tagpath): - node = getNode(node_s, tagpath) - if not node: - return None - return getNodeText(node) - -def getChildElts(node): - """get only child elements""" - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) - -def getNode(node, tagpath): - """returns the *first* matching node for given tag path.""" - - tags = tagpath.split('/') - - # iterative code to search for the path - - # get DOM for top node - nodeList = node.getElementsByTagName(tags[0]) - if len(nodeList) == 0: - return None # not found - - node = nodeList[0] # discard other matches - for tag in tags[1:]: - nodeList = node.getElementsByTagName(tag) - if len(nodeList) == 0: - return None - else: - node = nodeList[0] - - return node - -def getAllNodes(node, tags): - """retrieve all nodes that match a given tag path.""" - - if len(tags) == 0: - return [] - - nodeList = node.getElementsByTagName(tags[0]) - if len(nodeList) == 0: - return [] - - for tag in tags[1:]: - results = map(lambda x: x.getElementsByTagName(tag),nodeList) - nodeList = [] - for x in results: - nodeList.extend(x) - pass # emacs indentation error, keep it here - - if len(nodeList) == 0: - return [] - - return nodeList - - -# xmlfile class that further abstracts a dom object - -class XmlFile(object): - """A class for retrieving information from an XML file""" - - def __init__(self, rootTag): - self.rootTag = rootTag - - def readxml(self, fileName): - self.dom = mdom.parse(fileName) - - def writexml(self, fileName): - f = file(fileName,'w') - self.dom.writexml(f) - - def verifyRootTag(self): - if self.dom.documentElement.tagName != self.rootTag: - raise XmlError("Root tagname not " + self.rootTag + " as expected") - - def getNode(self, tagPath): - """returns the *first* matching node for given tag path.""" - self.verifyRootTag() - return getNode(self.dom.documentElement, tagPath) - - def getAllNodes(self, tagPath): - """returns all nodes matching a given tag path.""" - self.verifyRootTag() - tags = tagPath.split('/') - return getAllNodes(self.dom.documentElement, tags) - - def getChildren(self, tagpath): - """ returns the children of the given path""" - node = self.getNode(tagpath) - return node.childNodes - - # get only elements of a given type - # BUG: this doesn't work - def getChildrenWithType(self, tagpath, type): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - return filter(lambda x:x.nodeType == type, node.childNodes) - - # get only child elements - def getChildElts(self, tagpath): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - try: - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) - except AttributeError: - return None - - def getChildText(self, tagpath): - node = self.getNode(tagpath) - if not node: - return None - return getNodeText(node) -