diff --git a/pisi/cli/commands.py b/pisi/cli/commands.py new file mode 100644 index 00000000..87cc0222 --- /dev/null +++ b/pisi/cli/commands.py @@ -0,0 +1,185 @@ +# helper functions +def cmdObject(cmd, fail=False): + commands = {"help": Help, + "build": Build, + "info": Info, + "install": Install, + "remove": Remove, + "index": Index, + "updatedb": UpdateDB} + + if commands.has_key(cmd): + obj = commands[cmd]() + return obj + + if fail: + print "Unrecognized command: ", cmd + sys.exit(1) + else: + return None + +class Command(object): + """generic help string for any command""" + def __init__(self): + # now for the real parser + self.parser = OptionParser(usage=usage_text, + version="%prog " + pisi.__version__) + self.options() + self.parser = commonopts(self.parser) + (self.options, args) = self.parser.parse_args() + self.args = args[1:] + + self.checkAuthInfo() + + def options(self): + """This is a fall back function. If the implementer module provides an + options function it will be called""" + pass + + def checkAuthInfo(self): + username = self.options.username + password = self.options.password + if not username and not password: + if config.username and config.password: + self.authInfo = (config.username, config.password) + return + elif username and password: + self.authInfo = (username, password) + return + + if username and self.options.getpass: + from getpass import getpass + password = getpass("Password: ") + self.authInfo = (username, password) + else: + self.authInfo = None + + def help(self): + print getattr(self, "__doc__") + +class Help(Command): + """prints usage""" + def __init__(self): + super(Help, self).__init__() + + def run(self): + if not self.args: + print usage_text + print self.parser.format_option_help() + return + + for arg in self.args: + obj = cmdObject(arg, True) + obj.help() +# print "\n",self.parser.format_option_help() + +class Build(Command): + """build: compile PISI package using a pspec.xml file""" + def __init__(self): + super(Build, self).__init__() + + def run(self): + if not self.args: + self.help() + return + + from pisi.cli import buildhelper + for arg in self.args: + buildhelper.build(arg, self.authInfo) + +class Install(Command): + """install: install PISI packages""" + def __init__(self): + super(Install, self).__init__() + + def options(self): + self.parser.add_option("", "--test", action="store_true", + default=True, help="xxxx") + + def run(self): + if not self.args: + self.help() + return + + from pisi.cli import installhelper + for arg in self.args: + url = PUrl(packagefile) + if url.isRemoteFile(): + pass # bunu simdilik bosverelim, once bir calissin :) + + pi = Installer(url.uri) + pi.install() + + + +class Remove(Command): + """remove: remove PISI packages""" + def __init__(self): + super(Remove, self).__init__() + + def options(self): + self.parser.add_option("", "--test", action="store_true", + default=True, help="xxxx") + + def run(self): + if not self.args: + self.help() + return + + for arg in self.args: + pisi.install.remove(arg) + +class Info(Command): + """info: display information about a package + usage: info ...""" + def __init__(self): + super(Info, self).__init__() + + def run(self): + if not self.args: + self.help() + return + + for arg in self.args: + self.printinfo(arg) + + def printinfo(self, arg): + import os.path + if os.path.exists(arg): + metadata, files = pisi.install.get_pkg_info(arg) + print metadata.package + +class Index(Command): + """index: Index PISI files in a given directory""" + def __init__(self): + super(Index, self).__init__() + + def run(self): + if not self.args: + self.help() + return + + from pisi.cli import indexhelper + if len(self.args)==1: + indexhelper.index(self.args[0]) + elif len(self.args)==0: + indexhelper.index() + else: + print 'Indexing only a single directory supported' + return + +class UpdateDB(Command): + """updatedb: update source and package databases""" + def __init__(self): + super(UpdateDB, self).__init__() + + def run(self): + if len(self.args) != 1: + self.help() + return + + from pisi.cli import indexhelper + indexfile = self.args[0] + indexhelper.updatedb(indexfile) + + diff --git a/pisi/cli/installhelper.py b/pisi/cli/installhelper.py deleted file mode 100644 index 5f5482d0..00000000 --- a/pisi/cli/installhelper.py +++ /dev/null @@ -1,14 +0,0 @@ - -from pisi.install import PisiInstall -from pisi.context import InstallContext -from pisi.purl import PUrl - -def install(packagefile): - url = PUrl(packagefile) - if url.isRemoteFile(): - pass # bunu simdilik bosverelim, once bir calissin :) - else: - ctx = InstallContext(url.uri) - - pi = PisiInstall(ctx) - pi.install() diff --git a/pisi/cli/pisicli.py b/pisi/cli/pisicli.py index ce6f505f..0ba4e818 100644 --- a/pisi/cli/pisicli.py +++ b/pisi/cli/pisicli.py @@ -5,7 +5,9 @@ from optparse import OptionParser import pisi from pisi.config import config - +import pisi.operations +from pisi.purl import PUrl +from commands import * # globals usage_text = """%prog [options] [arguments] @@ -25,25 +27,6 @@ Use \"%prog help \" for help on a specific subcommand. PISI Package Manager """ -# helper functions -def cmdObject(cmd, fail=False): - commands = {"help": Help, - "build": Build, - "info": Info, - "install": Install, - "remove": Remove, - "index": Index, - "updatedb": UpdateDB} - - if commands.has_key(cmd): - obj = commands[cmd]() - return obj - - if fail: - print "Unrecognized command: ", cmd - sys.exit(1) - else: - return None def commonopts(parser): p = parser @@ -63,166 +46,6 @@ def commonopts(parser): return p -######## start commands ######### -class Command(object): - """generic help string for any command""" - def __init__(self): - # now for the real parser THIS IS ABSOLUTELY NECESSARY - self.parser = OptionParser(usage=usage_text, - version="%prog " + pisi.__version__) - #self.parser.allow_interspersed_args = False - self.options() - self.parser = commonopts(self.parser) - (self.options, args) = self.parser.parse_args() - self.args = args[1:] - - self.checkAuthInfo() - - def options(self): - """This is a fall back function. If the implementer module provides an - options function it will be called""" - pass - - def checkAuthInfo(self): - username = self.options.username - password = self.options.password - if not username and not password: - if config.username and config.password: - self.authInfo = (config.username, config.password) - return - elif username and password: - self.authInfo = (username, password) - return - - if username and self.options.getpass: - from getpass import getpass - password = getpass("Password: ") - self.authInfo = (username, password) - else: - self.authInfo = None - - def help(self): - print getattr(self, "__doc__") - -class Help(Command): - """prints usage""" - def __init__(self): - super(Help, self).__init__() - - def run(self): - if not self.args: - print usage_text - print self.parser.format_option_help() - return - - for arg in self.args: - obj = cmdObject(arg, True) - obj.help() -# print "\n",self.parser.format_option_help() - -class Build(Command): - """build: compile PISI package using a pspec.xml file""" - def __init__(self): - super(Build, self).__init__() - - def run(self): - if not self.args: - self.help() - return - - from pisi.cli import buildhelper - for arg in self.args: - buildhelper.build(arg, self.authInfo) - -class Install(Command): - """install: install PISI packages""" - def __init__(self): - super(Install, self).__init__() - - def options(self): - self.parser.add_option("", "--test", action="store_true", - default=True, help="xxxx") - - def run(self): - if not self.args: - self.help() - return - - from pisi.cli import installhelper - for arg in self.args: - installhelper.install(arg) - - -class Remove(Command): - """remove: remove PISI packages""" - def __init__(self): - super(Remove, self).__init__() - - def options(self): - self.parser.add_option("", "--test", action="store_true", - default=True, help="xxxx") - - def run(self): - if not self.args: - self.help() - return - - for arg in self.args: - pisi.install.remove(arg) - -class Info(Command): - """info: display information about a package - usage: info ...""" - def __init__(self): - super(Info, self).__init__() - - def run(self): - if not self.args: - self.help() - return - - for arg in self.args: - self.printinfo(arg) - - def printinfo(self, arg): - import os.path - if os.path.exists(arg): - metadata, files = pisi.install.get_pkg_info(arg) - print metadata.package - -class Index(Command): - """index: Index PISI files in a given directory""" - def __init__(self): - super(Index, self).__init__() - - def run(self): - if not self.args: - self.help() - return - - from pisi.cli import indexhelper - if len(self.args)==1: - indexhelper.index(self.args[0]) - elif len(self.args)==0: - indexhelper.index() - else: - print 'Indexing only a single directory supported' - return - -class UpdateDB(Command): - """updatedb: update source and package databases""" - def __init__(self): - super(UpdateDB, self).__init__() - - def run(self): - if len(self.args) != 1: - self.help() - return - - from pisi.cli import indexhelper - indexfile = self.args[0] - indexhelper.updatedb(indexfile) -######## end commands ######### class ParserError(Exception): pass diff --git a/pisi/context.py b/pisi/context.py index a9072ce0..2482c346 100644 --- a/pisi/context.py +++ b/pisi/context.py @@ -6,9 +6,6 @@ from constants import const from config import Config from specfile import SpecFile -from package import Package -from metadata import MetaData -from files import Files class BuildContext(object): """Build Context Singleton""" @@ -52,63 +49,3 @@ class BuildContext(object): def __setattr__(self, attr, value): return setattr(self.__instance, attr, value) - - -class InstallContext(object): - """Build Context Singleton""" - - class ctximpl(Config.configimpl): # singleton implementation - - def __init(self): - super(ctximpl, self).__init__() - - def setPackage(self, packagefile): - self.packagefile = packagefile - self.package = Package(packagefile, 'r') - - tmpdir = self.tmp_dir() - # extract control files - self.package.extract_PISI_files(tmpdir) - - # read files.xml and metadata.xml - mdxml = tmpdir + '/' + const.metadata_xml - self.setMetadataXML(mdxml) - filesxml = tmpdir + '/' + const.files_xml - self.setFilesXML(filesxml) - - def setMetadataXML(self, metadataxml): - self.metadataxml = metadataxml - metadata = MetaData() - metadata.read(metadataxml) - if not metadata.verify(): - raise InstallError("MetaData format wrong") - - self.metadata = metadata - - def setFilesXML(self, filesxml): - self.filesxml = filesxml - files = Files() - files.read(filesxml) - - self.files = files - - def pkg_dir(self): - packageDir = self.metadata.package.name + '-' \ - + self.metadata.package.version + '-' \ - + self.metadata.package.release - - return self.lib_dir() + '/' + packageDir - - def comar_dir(self): - return self.pkg_dir() + const.comar_dir_suffix - - __instance = ctximpl() # singleton implementation - - def __init__(self, packagefile): - self.__instance.setPackage(packagefile) - - def __getattr__(self, attr): - return getattr(self.__instance, attr) - - def __setattr__(self, attr, value): - return setattr(self.__instance, attr, value) diff --git a/pisi/install.py b/pisi/install.py index dab49350..11b342eb 100644 --- a/pisi/install.py +++ b/pisi/install.py @@ -35,24 +35,11 @@ class InstallError(Exception): # gönderilmesi gereksiz bence. Dahası bu PisiBuild ile de uyumlu bir # implemantation olduğu için daha rahat anlaşılır bir kod tabanı # oluşturuyor. (baris) -def remove(package_name): - """Remove a goddamn package""" - ui.info('Removing package ' + package_name) - if not installdb.is_installed(package_name): - raise InstallError('Trying to remove nonexistent package ' - + package_name) - for fileinfo in installdb.files(package_name): - os.unlink(fileinfo.path) - installdb.remove(package_name) -class PisiInstall: - "PisiInstall class, provides install rutines for pisi packages" - def __init__(self, installcontext): - self.ctx = installcontext - ## bu context fikri multi package installation fikriyle - ## uyusmuyor ne yazik ki. gitmesi gerek. - # +class Installer: + "Installer class, provides install rutines for pisi packages" + def __init__(self, package_fname): # Ben buna karşıyım. Multi-package işini kotarmak yalnızca # install'da değil hemen hemen tüm işlemlerde halletmemiz # gereken bir iş. Build, install, remove, upgrade, vs. hemen @@ -62,9 +49,10 @@ class PisiInstall: # tek pspec.xml dosyasından peket derlediği gibi. Biz bu # modülleri kullanarak üst seviye modüller ile çoklu paketler # işini halletmeliyiz. (baris) - self.metadata = self.ctx.metadata - self.files = self.ctx.files - self.package = self.ctx.package + self.package = Package(package_fname) + self.package.read() + self.metadata = self.package.metadata + self.files = self.package.files def extractInstall(self): ui.info('Extracting files\n') @@ -74,24 +62,23 @@ class PisiInstall: # put files.xml, metadata.xml, actions.py and COMAR scripts # somewhere in the file system. We'll need these in future... - #BUG: these look like they ought to be part of Package class ui.info('Storing %s\n' % const.files_xml) - self.package.extract_file(const.files_xml, self.ctx.pkg_dir()) + self.package.extract_file(const.files_xml, self.package.pkg_dir()) ui.info('Storing %s\n' % const.metadata_xml) - self.package.extract_file(const.metadata_xml, self.ctx.pkg_dir()) + self.package.extract_file(const.metadata_xml, self.package.pkg_dir()) for pcomar in self.metadata.package.providesComar: fpath = os.path.join(const.comar_dir, pcomar.script) # comar prefix is added to the pkg_dir while extracting comar # script file. so we'll use pkg_dir as destination. ui.info('Storing %s\n' % fpath) - self.package.extract_file(fpath, self.ctx.pkg_dir()) + self.package.extract_file(fpath, self.package.pkg_dir()) def registerCOMARScripts(self): # register COMAR scripts for pcomar in self.metadata.package.providesComar: - scriptPath = os.path.join(self.ctx.comar_dir(),pcomar.script) + scriptPath = os.path.join(self.package.comar_dir(),pcomar.script) ui.info("Registering COMAR script %s\n" % pcomar.script) ret = comariface.registerScript(pcomar.om, self.metadata.package.name, diff --git a/pisi/operations.py b/pisi/operations.py new file mode 100644 index 00000000..0bf6088a --- /dev/null +++ b/pisi/operations.py @@ -0,0 +1,17 @@ +# all package operation interfaces are here + +def remove(package_name): + """Remove a goddamn package""" + ui.info('Removing package ' + package_name) + if not installdb.is_installed(package_name): + raise InstallError('Trying to remove nonexistent package ' + + package_name) + for fileinfo in installdb.files(package_name): + os.unlink(fileinfo.path) + installdb.remove(package_name) + + +from install import Installer + +def install(package_name): + Installer diff --git a/pisi/package.py b/pisi/package.py index 11088f53..f62595af 100644 --- a/pisi/package.py +++ b/pisi/package.py @@ -6,6 +6,12 @@ import archive from constants import const from config import config from purl import PUrl +from os.path import join +from metadata import MetaData +from files import Files + +class PackageError: + pass class Package: """PISI Package Class provides access to a pisi package (.pisi @@ -62,3 +68,28 @@ class Package: self.extract_files([const.metadata_xml, const.files_xml], outdir) self.extract_dir('config', outdir) + def read_info(self, outdir = None): + if not outdir: + outdir = config.tmp_dir() + + # extract control files + self.package.extract_PISI_files(tmpdir) + + filesxml = + self.metadata = MetaData() + self.metadata.read( join(tmpdir, config.metadata_xml) ) + if not metadata.verify(): + raise PackageError("MetaData format wrong") + + self.files = Files() + self.files.read( join(tmpdir, const.files_xml) ) + + def pkg_dir(self): + packageDir = self.metadata.package.name + '-' \ + + self.metadata.package.version + '-' \ + + self.metadata.package.release + + return join( config.lib_dir(), packageDir) + + def comar_dir(self): + return join( self.pkg_dir(), const.comar_dir_suffix)