catalog.py revision 36
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#!/usr/bin/python
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# CDDL HEADER START
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# The contents of this file are subject to the terms of the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# Common Development and Distribution License (the "License").
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# You may not use this file except in compliance with the License.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# or http://www.opensolaris.org/os/licensing.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# See the License for the specific language governing permissions
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# and limitations under the License.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# When distributing Covered Code, include this CDDL HEADER in each
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# If applicable, add the following below this CDDL HEADER, with the
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# fields enclosed by brackets "[]" replaced with your own identifying
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# information: Portions Copyright [yyyy] [name of copyright owner]
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# CDDL HEADER END
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk#
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk# Use is subject to license terms.
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport os
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport re
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport sha
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport shutil
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport time
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport urllib
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport pkg.fmri as fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkimport pkg.package as package
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkclass Catalog(object):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk """A Catalog is the representation of the package FMRIs available to
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk this client or repository. Both purposes utilize the same storage
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk format.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk The serialized structure of the repository is an unordered list of
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk available package versions, followed by an unordered list of
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk incorporation relationships between packages. This latter section
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk allows the graph to be topologically sorted by the client.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk V fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk V fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ...
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk I fmri fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk I fmri fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk ...
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk XXX It would be nice to include available tags and package sizes,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk although this could also be calculated from the set of manifests.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk """
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def __init__(self):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.authority = None
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.catalog_root = ""
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.pkgs = []
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.relns = {}
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def set_authority(self, authority):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.authority = authority
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def set_catalog_root(self, croot):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.catalog_root = croot
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def load(self, path):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.path = path
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk cfile = file(path, "r")
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk centries = cfile.readlines()
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for entry in centries:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # each V line is an fmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk m = re.match("^V (pkg:[^ ]*)", entry)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if m == None:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk continue
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pname = m.group(1)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.add_fmri(fmri.PkgFmri(pname, None))
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def add_fmri(self, pkgfmri):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk name = pkgfmri.get_pkg_stem()
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pfmri = fmri.PkgFmri(name, None)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for pkg in self.pkgs:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if pfmri == pkg.fmri:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pkg.add_version(pkgfmri)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pkg = package.Package(pfmri)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pkg.add_version(pkgfmri)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.pkgs.append(pkg)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def add_pkg(self, pkg):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for opkg in self.pkgs:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # XXX XXX
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if pkg.fmri == opkg.fmri:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if not pkg in self.pkgs:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk self.pkgs.append(pkg)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # for each version in the package,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # for each incorporation in the version,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # add to the version's list of incorporations
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def add_package_fmri(self, pkg_fmri):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def delete_package_fmri(self, pkg_fmri):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def get_matching_pkgs(self, pfmri, constraint):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk """Iterate through the catalog's, looking for an fmri match."""
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # XXX FMRI-based implementation doesn't do pattern matching, but
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk # exact matches only.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk pf = fmri.PkgFmri(pfmri, None)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for pkg in self.pkgs:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk if pkg.fmri.is_similar(pf):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return pkg.matching_versions(pfmri, constraint)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk raise KeyError, "%s not found in catalog" % pfmri
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def __str__(self):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk s = ""
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for p in self.pkgs:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk s = s + p.get_catalog_entry()
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk for r in self.relns:
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk s = s + "I %s\n" % r
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return s
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk def difference(self, catalog):
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk """Return a pair of lists, the first list being those package
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk FMRIs present in the current object but not in the presented
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk catalog, the second being those present in the presented catalog
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk but not in the current catalog."""
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk return
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk