* 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
|
# 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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user