* finish implementation of sourcedb

- hook it to update-repo
 - new command: list-sources
* start implementing emerge
* reorganize a bit for the upcoming changes
This commit is contained in:
Eray Özkural
2006-03-08 01:21:34 +00:00
parent 4edcb6954c
commit 67938150e3
9 changed files with 248 additions and 19 deletions
+2 -2
View File
@@ -12,9 +12,9 @@
# PiSi version # PiSi version
__version__ = "1.0.3" __version__ = "1.0.4"
__dbversion__ = "1.0.2" __dbversion__ = "1.0.4"
__all__ = [ 'api', 'config', 'packagedb', 'installdb', 'search' ] __all__ = [ 'api', 'config', 'packagedb', 'installdb', 'search' ]
+5 -4
View File
@@ -37,9 +37,9 @@ import pisi.sourcedb
import pisi.component as component import pisi.component as component
from pisi.index import Index from pisi.index import Index
import pisi.cli import pisi.cli
from pisi.operations import install, remove, upgrade from pisi.operations import install, remove, upgrade, emerge
from pisi.build import build, build_until from pisi.build import build_until
from pisi.atomicoperations import resurrect_package from pisi.atomicoperations import resurrect_package, build
from pisi.metadata import MetaData from pisi.metadata import MetaData
from pisi.files import Files from pisi.files import Files
import pisi.search import pisi.search
@@ -73,13 +73,14 @@ def init(database = True, options = None, ui = None, comar = True):
ctx.filesdb = pisi.files.FilesDB() ctx.filesdb = pisi.files.FilesDB()
ctx.componentdb = pisi.component.ComponentDB() ctx.componentdb = pisi.component.ComponentDB()
packagedb.init_db() packagedb.init_db()
pisi.sourcedb.init() ctx.sourcedb = pisi.sourcedb.init()
pisi.search.init(['summary', 'description'], ['en', 'tr']) pisi.search.init(['summary', 'description'], ['en', 'tr'])
else: else:
ctx.repodb = None ctx.repodb = None
ctx.installdb = None ctx.installdb = None
ctx.filesdb = None ctx.filesdb = None
ctx.componentdb = None ctx.componentdb = None
ctx.sourcedb = None
ctx.ui.debug('PISI API initialized') ctx.ui.debug('PISI API initialized')
ctx.initialized = True ctx.initialized = True
+8
View File
@@ -429,6 +429,14 @@ class Remove(AtomicOperation):
def remove_single(package_name): def remove_single(package_name):
Remove(package_name).run() Remove(package_name).run()
def build(package, authinfo=None):
# wrapper for build op`
if package.endswith('.xml'):
import pisi.build
pisi.build.build(package, authinfo)
#else:
# ...
def __is_virtual_upgrade(metadata): def __is_virtual_upgrade(metadata):
pkg = metadata.package pkg = metadata.package
+1 -1
View File
@@ -43,7 +43,7 @@ import pisi.component as component
class Error(pisi.Error): class Error(pisi.Error):
pass pass
# Helper Functions # Helper Functions
def get_file_type(path, pinfo_list, install_dir): def get_file_type(path, pinfo_list, install_dir):
"""Return the file type of a path according to the given PathInfo """Return the file type of a path according to the given PathInfo
+43 -3
View File
@@ -320,10 +320,14 @@ def ignoredep_opt(self):
class Build(Command): class Build(Command):
"""Build a PISI package using a pspec.xml file """Build a PISI package using a pspec.xml file
Usage: build <pspec.xml> Usage: build [<pspec.xml> | <sourcename>] ...
You can give a URI of the pspec.xml file. PISI will You can give a URI of the pspec.xml file. PISI will
fetch all necessary files and build the package for you. fetch all necessary files and build the package for you.
Alternatively, you can give the name of a source package
to be downloaded from a repository containing sources.
""" """
__metaclass__ = autocommand __metaclass__ = autocommand
@@ -350,8 +354,8 @@ fetch all necessary files and build the package for you.
self.init(database = True) self.init(database = True)
ctx.ui.info(_('Output directory: %s') % ctx.config.options.output_dir) ctx.ui.info(_('Output directory: %s') % ctx.config.options.output_dir)
for arg in self.args: for x in self.args:
pisi.api.build(arg, self.authInfo) pisi.api.build(x, self.authInfo)
self.finalize() self.finalize()
@@ -935,6 +939,42 @@ Gives a brief list of PiSi components published in the repositories.
self.finalize() self.finalize()
class ListSources(Command):
"""List available sources
Usage: list-sources
Gives a brief list of sources published in the repositories.
"""
__metaclass__ = autocommand
def __init__(self):
super(ListSources, self).__init__()
name = ("list-sources", "ls")
def options(self):
self.parser.add_option("-l", "--long", action="store_true",
default=False, help=_("show in long format"))
def run(self):
self.init(True)
list = ctx.sourcedb.list()
list.sort()
for p in list:
source = ctx.sourcedb.get_source(p)
if self.options.long:
ctx.ui.info(unicode(component))
else:
lenp = len(p)
#if p in installed_list:
# p = colorize(p, 'cyan')
p = p + ' ' * max(0, 15 - lenp)
ctx.ui.info('%s - %s ' % (source.name, unicode(source.summary)))
self.finalize()
class ListUpgrades(Command): class ListUpgrades(Command):
"""List packages to be upgraded """List packages to be upgraded
+3
View File
@@ -26,6 +26,7 @@ import pisi.context as ctx
import pisi.specfile as specfile import pisi.specfile as specfile
import pisi.metadata as metadata import pisi.metadata as metadata
import pisi.packagedb as packagedb import pisi.packagedb as packagedb
import pisi.sourcedb as sourcedb
import pisi.util as util import pisi.util as util
from pisi.package import Package from pisi.package import Package
from pisi.pxml.xmlfile import XmlFile from pisi.pxml.xmlfile import XmlFile
@@ -85,6 +86,8 @@ class Index(XmlFile):
ctx.componentdb.update_component(comp) ctx.componentdb.update_component(comp)
for pkg in self.packages: for pkg in self.packages:
pkgdb.add_package(pkg) pkgdb.add_package(pkg)
for src in self.sources:
ctx.sourcedb.add_source(src, repo)
def add_package(self, path, repo_uri): def add_package(self, path, repo_uri):
package = Package(path, 'r') package = Package(path, 'r')
+145
View File
@@ -41,6 +41,7 @@ class Error(pisi.Error):
pass pass
# high level operations # high level operations
def install(packages, reinstall = False): def install(packages, reinstall = False):
"""install a list of packages (either files/urls, or names)""" """install a list of packages (either files/urls, or names)"""
@@ -495,3 +496,147 @@ def plan_remove(A):
G_f.write_graphviz(sys.stdout) G_f.write_graphviz(sys.stdout)
order = G_f.topological_sort() order = G_f.topological_sort()
return G_f, order return G_f, order
def expand_src_components(A):
Ap = set()
for x in A:
if ctx.componentdb.has_component(x):
Ap = Ap.union(ctx.componentdb.get_component(x).sources)
else:
Ap.add(x)
return Ap
##def build_names(A, rebuild = true):
##
## # A was a list, remove duplicates and expand components
## A_0 = A = expand_src_components(set(A))
## ctx.ui.debug('A = %s' % str(A))
##
## # filter packages that are already installed
## if not rebuild:
## Ap = set(filter(lambda x: not ctx.installdb.is_installed(x), A))
## d = A - Ap
## if len(d) > 0:
## ctx.ui.warning(_('Not re-building the following packages: ') +
## util.strlist(d))
## A = Ap
##
## if len(A)==0:
## ctx.ui.info(_('No packages to build.'))
## return
##
## if not ctx.config.get_option('ignore_dependency'):
## G_f, order_inst = plan_build_pkg_names(A)
## else:
## G_f = None
## order_inst = []
##
## ctx.ui.info(_("""The following minimal list of packages will be installed
##in the respective order to satisfy dependencies:
##""") + util.strlist(order))
##
## if ctx.get_option('dry_run'):
## return
##
## if len(order) > len(A_0):
## if not ctx.ui.confirm(_('There are extra packages due to dependencies. Do you want to continue?')):
## return False
##
## ctx.ui.notify(ui.packagestogo, order = order)
##
## for x in order:
## atomicoperations.install_single_name(x)
##
##def plan_build_names(A):
## # try to construct a pisi graph of packages to
## # install / reinstall
##
## G_f = pgraph.PGraph(packagedb) # construct G_f
##
## # find the "install closure" graph of G_f by package
## # set A using packagedb
## for x in A:
## G_f.add_package(x)
## B = A
##
## while len(B) > 0:
## Bp = set()
## for x in B:
## pkg = packagedb.get_package(x)
## for dep in pkg.runtimeDependencies():
## ctx.ui.debug('checking %s' % str(dep))
## # we don't deal with already *satisfied* dependencies
## if not dependency.installed_satisfies_dep(dep):
## if not dep.package in G_f.vertices():
## Bp.add(str(dep.package))
## G_f.add_dep(x, dep)
## B = Bp
## if ctx.config.get_option('debug'):
## G_f.write_graphviz(sys.stdout)
## order = G_f.topological_sort()
## order.reverse()
## check_conflicts(order)
## return G_f, order
def emerge(A):
# A was a list, remove duplicates and expand components
A_0 = A = expand_src_components(set(A))
ctx.ui.debug('A = %s' % str(A))
if len(A)==0:
ctx.ui.info(_('No packages to build.'))
return
if not ctx.config.get_option('ignore_dependency'):
G_f, order = plan_emerge(A)
else:
G_f = None
order_inst = []
ctx.ui.info(_("""The following minimal list of packages will be built and
installed in the respective order to satisfy dependencies:
""") + util.strlist(order))
if ctx.get_option('dry_run'):
return
if len(order) > len(A_0):
if not ctx.ui.confirm(_('There are extra packages due to dependencies. Do you want to continue?')):
return False
ctx.ui.notify(ui.packagestogo, order = order)
for x in order:
atomicoperations.install_single_name(x)
def plan_emerge(A):
# try to construct a pisi graph of packages to
# install / reinstall
G_f = pgraph.PGraph(packagedb) # construct G_f
# find the "install closure" graph of G_f by package
# set A using packagedb
for x in A:
G_f.add_package(x)
B = A
while len(B) > 0:
Bp = set()
for x in B:
pkg = packagedb.get_package(x)
for dep in pkg.runtimeDependencies():
ctx.ui.debug('checking %s' % str(dep))
# we don't deal with already *satisfied* dependencies
if not dependency.installed_satisfies_dep(dep):
if not dep.package in G_f.vertices():
Bp.add(str(dep.package))
G_f.add_dep(x, dep)
B = Bp
if ctx.config.get_option('debug'):
G_f.write_graphviz(sys.stdout)
order = G_f.topological_sort()
order.reverse()
check_conflicts(order)
return G_f, order
+1 -1
View File
@@ -51,7 +51,7 @@ class RepoDB(object):
# initialize package/source dbs # initialize package/source dbs
for x in self.list(): for x in self.list():
packagedb.add_db(x) packagedb.add_db(x)
def close(self): def close(self):
self.d.close() self.d.close()
+40 -8
View File
@@ -16,6 +16,9 @@ package source database
interface for update/query to local package repository interface for update/query to local package repository
we basically store everything in sourceinfo class we basically store everything in sourceinfo class
yes, we are cheap yes, we are cheap
to handle multiple repositories, for sources, we
store a set of repositories in which the source appears.
the actual guy to take is determined from the repo order.
""" """
import os import os
@@ -28,31 +31,60 @@ _ = __trans.ugettext
import pisi.util as util import pisi.util as util
import pisi.context as ctx import pisi.context as ctx
import pisi.lockeddbshelve as shelve import pisi.lockeddbshelve as shelve
import pisi.repodb
class SourceDB(object): class SourceDB(object):
def __init__(self, id = 'repo'): def __init__(self):
self.d = shelve.LockedDBShelf('source-%s' % id) self.d = shelve.LockedDBShelf('source')
def close(self): def close(self):
self.d.close() self.d.close()
def list(self):
list = []
for (pkg, x) in self.d.items():
list.append(pkg) # for some reason we couldn't return self.d.items()!! --exa
return list
def has_source(self, name): def has_source(self, name):
name = str(name) name = str(name)
return self.d.has_key(name) return self.d.has_key(name)
def get_source(self, name): def get_source(self, name):
name = str(name) name = str(name)
return self.d[name] s = self.d[name]
order = ctx.repodb.list()
for repo in order:
if s.has_key(repo):
return s[repo]
return None
def add_source(self, source_info): def add_source(self, source_info, repo, txn = None):
assert not source_info.errors() assert not source_info.errors()
name = str(source_info.name) name = str(source_info.name)
self.d[name] = source_info repo = str(repo)
def proc(txn):
def remove_source(self, name): if not self.d.has_key(name):
s = dict()
else:
s = self.d[name]
s[repo] = source_info
self.d[name] = s
self.d.txn_proc(proc, txn)
def remove_source(self, name, repo):
name = str(name) name = str(name)
del self.d[name] repo = str(repo)
def proc(txn):
#assert self.has_source(name)
s = self.d[name]
s.remove(repo)
if (len(s)==0):
del self.d[name]
else:
self.d[name] = s
self.d.txn_proc(proc, txn)
sourcedb = None sourcedb = None