catalog.py revision 45
23N/A#!/usr/bin/python
23N/A#
23N/A# CDDL HEADER START
23N/A#
23N/A# The contents of this file are subject to the terms of the
23N/A# Common Development and Distribution License (the "License").
23N/A# You may not use this file except in compliance with the License.
23N/A#
23N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
23N/A# or http://www.opensolaris.org/os/licensing.
23N/A# See the License for the specific language governing permissions
23N/A# and limitations under the License.
23N/A#
23N/A# When distributing Covered Code, include this CDDL HEADER in each
23N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
23N/A# If applicable, add the following below this CDDL HEADER, with the
23N/A# fields enclosed by brackets "[]" replaced with your own identifying
23N/A# information: Portions Copyright [yyyy] [name of copyright owner]
23N/A#
23N/A# CDDL HEADER END
23N/A#
23N/A# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23N/A# Use is subject to license terms.
23N/A
23N/Aimport os
23N/Aimport re
23N/Aimport sha
23N/Aimport shutil
23N/Aimport time
23N/Aimport urllib
23N/A
23N/Aimport pkg.fmri as fmri
36N/Aimport pkg.package as package
23N/A
34N/Aclass Catalog(object):
34N/A """A Catalog is the representation of the package FMRIs available to
34N/A this client or repository. Both purposes utilize the same storage
34N/A format.
24N/A
26N/A The serialized structure of the repository is an unordered list of
26N/A available package versions, followed by an unordered list of
26N/A incorporation relationships between packages. This latter section
26N/A allows the graph to be topologically sorted by the client.
26N/A
50N/A XXX A authority mirror-uri ...
50N/A XXX ...
37N/A
37N/A V fmri
37N/A V fmri
26N/A ...
26N/A I fmri fmri
26N/A I fmri fmri
50N/A ...
50N/A
50N/A XXX Mirroring records also need to be allowed from client configuration,
26N/A and not just catalogs.
26N/A
26N/A XXX It would be nice to include available tags and package sizes,
59N/A although this could also be calculated from the set of manifests.
37N/A
59N/A XXX self.pkgs should be a dictionary, accessed by fmri string (or
59N/A package name). Current code is O(N_packages) O(M_versions), should be
59N/A O(1) O(M_versions), and possibly O(1) O(1).
59N/A """
59N/A
59N/A def __init__(self):
59N/A self.catalog_root = ""
59N/A
59N/A self.authorities = {}
59N/A self.pkgs = []
59N/A self.relns = {}
59N/A
59N/A def add_authority(self, authority, urls):
59N/A self.authorities[authority] = urls
59N/A
23N/A def delete_authority(self, authority):
23N/A del(self.authorities[authority])
34N/A
34N/A def set_catalog_root(self, croot):
50N/A self.catalog_root = croot
50N/A
50N/A def load(self, path):
45N/A self.path = path
26N/A cfile = file(path, "r")
50N/A centries = cfile.readlines()
50N/A
24N/A for entry in centries:
23N/A # each V line is an fmri
45N/A m = re.match("^V (pkg:[^ ]*)", entry)
45N/A if m == None:
45N/A continue
45N/A
45N/A pname = m.group(1)
34N/A self.add_fmri(fmri.PkgFmri(pname, None))
34N/A
34N/A def add_fmri(self, pkgfmri):
34N/A name = pkgfmri.get_pkg_stem()
36N/A pfmri = fmri.PkgFmri(name, None)
36N/A
36N/A for pkg in self.pkgs:
36N/A if pkg.fmri.is_same_pkg(pfmri):
36N/A pkg.add_version(pkgfmri)
36N/A return
36N/A
36N/A pkg = package.Package(pfmri)
50N/A pkg.add_version(pkgfmri)
50N/A self.pkgs.append(pkg)
50N/A
36N/A def add_pkg(self, pkg):
50N/A for opkg in self.pkgs:
50N/A if pkg.fmri == opkg.fmri:
50N/A #
50N/A # XXX This package is already in the catalog
50N/A # with some version set. Are we updating the
50N/A # version set or merging the two?
50N/A #
50N/A opkg = pkg
50N/A return
36N/A
36N/A self.pkgs.append(pkg)
36N/A
36N/A def add_package_fmri(self, pkg_fmri):
36N/A return
36N/A
39N/A def delete_package_fmri(self, pkg_fmri):
36N/A return
36N/A
36N/A def get_matching_pkgs(self, pfmri, constraint):
36N/A """Iterate through the catalog's, looking for an fmri match."""
36N/A
36N/A # XXX FMRI-based implementation doesn't do pattern matching, but
36N/A # exact matches only.
50N/A pf = fmri.PkgFmri(pfmri, None)
36N/A
36N/A for pkg in self.pkgs:
37N/A if pkg.fmri.is_similar(pf):
37N/A return pkg.matching_versions(pfmri, constraint)
37N/A
37N/A raise KeyError, "%s not found in catalog" % pfmri
37N/A
37N/A def __str__(self):
37N/A s = ""
26N/A for p in self.pkgs:
37N/A s = s + p.get_catalog_entry()
50N/A for r in self.relns:
50N/A s = s + "I %s\n" % r
34N/A return s
36N/A
50N/A def display(self):
50N/A for p in self.pkgs:
36N/A print "%-50s" % p.fmri
30N/A for v in p.pversions:
59N/A print " %20s" % v.version
30N/A
30N/A def difference(self, catalog):
50N/A """Return a pair of lists, the first list being those package
50N/A FMRIs present in the current object but not in the presented
50N/A catalog, the second being those present in the presented catalog
50N/A but not in the current catalog."""
50N/A return
50N/A
50N/Aif __name__ == "__main__":
50N/A c = Catalog()
50N/A
50N/A for f in [
50N/A fmri.PkgFmri("pkg:/test@1.0,5.11-1:100", None),
50N/A fmri.PkgFmri("pkg:/test@1.0,5.11-1:110", None),
50N/A fmri.PkgFmri("pkg:/test@1.0,5.11-1.1:120", None),
50N/A fmri.PkgFmri("pkg:/test@1.0,5.11-1.2:130", None),
50N/A fmri.PkgFmri("pkg:/test@1.0,5.11-2:140", None),
50N/A fmri.PkgFmri("pkg:/test@1.1,5.11-1:140", None)
50N/A ]:
50N/A c.add_fmri(f)
50N/A
50N/A print c
30N/A
24N/A tps = [
24N/A "pkg:/test@1.0,5.10-1:105",
50N/A "pkg:/test@1.0,5.11-1:50",
50N/A "pkg:/test@1.0,5.11-2",
26N/A "pkg:/test@1.0,5.11-3"
36N/A ]
50N/A
50N/A for tp in tps:
24N/A print "matches for %s:" % tp
26N/A
24N/A for p in c.get_matching_pkgs(tp, None):
24N/A print " ", p
45N/A