* 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:
+2
-2
@@ -12,9 +12,9 @@
|
||||
|
||||
# PiSi version
|
||||
|
||||
__version__ = "1.0.3"
|
||||
__version__ = "1.0.4"
|
||||
|
||||
__dbversion__ = "1.0.2"
|
||||
__dbversion__ = "1.0.4"
|
||||
|
||||
__all__ = [ 'api', 'config', 'packagedb', 'installdb', 'search' ]
|
||||
|
||||
|
||||
+5
-4
@@ -37,9 +37,9 @@ import pisi.sourcedb
|
||||
import pisi.component as component
|
||||
from pisi.index import Index
|
||||
import pisi.cli
|
||||
from pisi.operations import install, remove, upgrade
|
||||
from pisi.build import build, build_until
|
||||
from pisi.atomicoperations import resurrect_package
|
||||
from pisi.operations import install, remove, upgrade, emerge
|
||||
from pisi.build import build_until
|
||||
from pisi.atomicoperations import resurrect_package, build
|
||||
from pisi.metadata import MetaData
|
||||
from pisi.files import Files
|
||||
import pisi.search
|
||||
@@ -73,13 +73,14 @@ def init(database = True, options = None, ui = None, comar = True):
|
||||
ctx.filesdb = pisi.files.FilesDB()
|
||||
ctx.componentdb = pisi.component.ComponentDB()
|
||||
packagedb.init_db()
|
||||
pisi.sourcedb.init()
|
||||
ctx.sourcedb = pisi.sourcedb.init()
|
||||
pisi.search.init(['summary', 'description'], ['en', 'tr'])
|
||||
else:
|
||||
ctx.repodb = None
|
||||
ctx.installdb = None
|
||||
ctx.filesdb = None
|
||||
ctx.componentdb = None
|
||||
ctx.sourcedb = None
|
||||
ctx.ui.debug('PISI API initialized')
|
||||
ctx.initialized = True
|
||||
|
||||
|
||||
@@ -429,6 +429,14 @@ class Remove(AtomicOperation):
|
||||
def remove_single(package_name):
|
||||
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):
|
||||
|
||||
pkg = metadata.package
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ import pisi.component as component
|
||||
class Error(pisi.Error):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
# Helper Functions
|
||||
def get_file_type(path, pinfo_list, install_dir):
|
||||
"""Return the file type of a path according to the given PathInfo
|
||||
|
||||
+43
-3
@@ -320,10 +320,14 @@ def ignoredep_opt(self):
|
||||
class Build(Command):
|
||||
"""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
|
||||
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
|
||||
|
||||
@@ -350,8 +354,8 @@ fetch all necessary files and build the package for you.
|
||||
|
||||
self.init(database = True)
|
||||
ctx.ui.info(_('Output directory: %s') % ctx.config.options.output_dir)
|
||||
for arg in self.args:
|
||||
pisi.api.build(arg, self.authInfo)
|
||||
for x in self.args:
|
||||
pisi.api.build(x, self.authInfo)
|
||||
self.finalize()
|
||||
|
||||
|
||||
@@ -935,6 +939,42 @@ Gives a brief list of PiSi components published in the repositories.
|
||||
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):
|
||||
"""List packages to be upgraded
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import pisi.context as ctx
|
||||
import pisi.specfile as specfile
|
||||
import pisi.metadata as metadata
|
||||
import pisi.packagedb as packagedb
|
||||
import pisi.sourcedb as sourcedb
|
||||
import pisi.util as util
|
||||
from pisi.package import Package
|
||||
from pisi.pxml.xmlfile import XmlFile
|
||||
@@ -85,6 +86,8 @@ class Index(XmlFile):
|
||||
ctx.componentdb.update_component(comp)
|
||||
for pkg in self.packages:
|
||||
pkgdb.add_package(pkg)
|
||||
for src in self.sources:
|
||||
ctx.sourcedb.add_source(src, repo)
|
||||
|
||||
def add_package(self, path, repo_uri):
|
||||
package = Package(path, 'r')
|
||||
|
||||
@@ -41,6 +41,7 @@ class Error(pisi.Error):
|
||||
pass
|
||||
|
||||
# high level operations
|
||||
|
||||
def install(packages, reinstall = False):
|
||||
"""install a list of packages (either files/urls, or names)"""
|
||||
|
||||
@@ -495,3 +496,147 @@ def plan_remove(A):
|
||||
G_f.write_graphviz(sys.stdout)
|
||||
order = G_f.topological_sort()
|
||||
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
@@ -51,7 +51,7 @@ class RepoDB(object):
|
||||
# initialize package/source dbs
|
||||
for x in self.list():
|
||||
packagedb.add_db(x)
|
||||
|
||||
|
||||
def close(self):
|
||||
self.d.close()
|
||||
|
||||
|
||||
+40
-8
@@ -16,6 +16,9 @@ package source database
|
||||
interface for update/query to local package repository
|
||||
we basically store everything in sourceinfo class
|
||||
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
|
||||
@@ -28,31 +31,60 @@ _ = __trans.ugettext
|
||||
import pisi.util as util
|
||||
import pisi.context as ctx
|
||||
import pisi.lockeddbshelve as shelve
|
||||
import pisi.repodb
|
||||
|
||||
class SourceDB(object):
|
||||
|
||||
def __init__(self, id = 'repo'):
|
||||
self.d = shelve.LockedDBShelf('source-%s' % id)
|
||||
def __init__(self):
|
||||
self.d = shelve.LockedDBShelf('source')
|
||||
|
||||
def close(self):
|
||||
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):
|
||||
name = str(name)
|
||||
return self.d.has_key(name)
|
||||
|
||||
def get_source(self, 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()
|
||||
name = str(source_info.name)
|
||||
self.d[name] = source_info
|
||||
|
||||
def remove_source(self, name):
|
||||
repo = str(repo)
|
||||
def proc(txn):
|
||||
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)
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user