manifest.py revision 2854
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#!/usr/bin/python
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# CDDL HEADER START
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# The contents of this file are subject to the terms of the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# Common Development and Distribution License (the "License").
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# You may not use this file except in compliance with the License.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# or http://www.opensolaris.org/os/licensing.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# See the License for the specific language governing permissions
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# and limitations under the License.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# When distributing Covered Code, include this CDDL HEADER in each
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# If applicable, add the following below this CDDL HEADER, with the
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# fields enclosed by brackets "[]" replaced with your own identifying
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# information: Portions Copyright [yyyy] [name of copyright owner]
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# CDDL HEADER END
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenfrom collections import namedtuple, defaultdict
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport errno
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport hashlib
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport os
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport tempfile
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenfrom itertools import groupby, chain, repeat, izip
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenfrom operator import itemgetter
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenimport pkg.actions as actions
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimport pkg.client.api_errors as apx
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimport pkg.misc as misc
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimport pkg.portable as portable
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimport pkg.variant as variant
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimport pkg.version as version
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenfrom pkg.misc import EmptyDict, EmptyI, expanddirs, PKG_FILE_MODE, PKG_DIR_MODE
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenfrom pkg.actions.attribute import AttributeAction
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenclass ManifestDifference(
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen namedtuple("ManifestDifference", "added changed removed")):
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen __slots__ = []
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen __state__desc = tuple([
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen [ ( actions.generic.NSG, actions.generic.NSG ) ],
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen [ ( actions.generic.NSG, actions.generic.NSG ) ],
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen [ ( actions.generic.NSG, actions.generic.NSG ) ],
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen ])
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen __state__commonize = frozenset([
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen actions.generic.NSG,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen ])
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen @staticmethod
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen def getstate(obj, je_state=None):
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen """Returns the serialized state of this object in a format
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen that that can be easily stored using JSON, pickle, etc."""
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return misc.json_encode(ManifestDifference.__name__,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen tuple(obj),
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ManifestDifference.__state__desc,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen commonize=ManifestDifference.__state__commonize,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen je_state=je_state)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen @staticmethod
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen def fromstate(state, jd_state=None):
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen """Allocate a new object using previously serialized state
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen obtained via getstate()."""
445f9e31c6c3aa6c0a72be8565da8f6e594d24fbTimo Sirainen
445f9e31c6c3aa6c0a72be8565da8f6e594d24fbTimo Sirainen # decode serialized state into python objects
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen state = misc.json_decode(ManifestDifference.__name__,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen state,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ManifestDifference.__state__desc,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen commonize=ManifestDifference.__state__commonize,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen jd_state=jd_state)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return ManifestDifference(*state)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenclass Manifest(object):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """A Manifest is the representation of the actions composing a specific
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen package version on both the client and the repository. Both purposes
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen utilize the same storage format.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen The serialized structure of a manifest is an unordered list of actions.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen The special action, "set", represents a package attribute.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen The reserved attribute, "fmri", represents the package and version
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen described by this manifest. It is available as a string via the
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen attributes dictionary, and as an FMRI object from the fmri member.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen The list of manifest-wide reserved attributes is
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen base_directory Default base directory, for non-user images.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen fmri Package FMRI.
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen isa Package is intended for a list of ISAs.
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen platform Package is intended for a list of platforms.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen relocatable Suitable for User Image.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen All non-prefixed attributes are reserved to the framework. Third
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen parties may prefix their attributes with a reversed domain name, domain
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen name, or stock symbol. An example might be
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen com.example,supported
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen as an indicator that a specific package version is supported by the
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen vendor, example.com.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen manifest.null is provided as the null manifest. Differences against the
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen null manifest result in the complete set of attributes and actions of
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen the non-null manifest, meaning that all operations can be viewed as
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen tranitions between the manifest being installed and the manifest already
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen present in the image (which may be the null manifest).
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen """
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen def __init__(self, pfmri=None):
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen self.fmri = pfmri
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen self._cache = {}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._facets = None # facets seen in package
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._variants = None # variants seen in package
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.actions = []
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.actions_bytype = {}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.attributes = {} # package-wide attributes
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.signatures = EmptyDict
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.excludes = EmptyI
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen def __str__(self):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen r = ""
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if "pkg.fmri" not in self.attributes and self.fmri != None:
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen r += "set name=pkg.fmri value=%s\n" % self.fmri
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen for act in sorted(self.actions):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen r += "%s\n" % act
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return r
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen def as_lines(self):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """A generator function that returns the unsorted manifest
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen contents as lines of text."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if "pkg.fmri" not in self.attributes and self.fmri != None:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield "set name=pkg.fmri value=%s\n" % self.fmri
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for act in self.actions:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield "%s\n" % act
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def tostr_unsorted(self):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return "".join((l for l in self.as_lines()))
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen def difference(self, origin, origin_exclude=EmptyI,
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen self_exclude=EmptyI):
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen """Return three lists of action pairs representing origin and
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen destination actions. The first list contains the pairs
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen representing additions, the second list contains the pairs
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen representing updates, and the third list contains the pairs
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen representing removals. All three lists are in the order in
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen which they should be executed."""
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # XXX Do we need to find some way to assert that the keys are
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # all unique?
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if isinstance(origin, EmptyFactoredManifest):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # No origin was provided, so nothing has been changed or
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # removed; only added. In addition, this doesn't need
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # to be sorted since the caller likely already does
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # (such as pkgplan/imageplan).
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return ManifestDifference(
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen [(None, a) for a in self.gen_actions(self_exclude)],
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen [], [])
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def hashify(v):
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen """handle key values that may be lists"""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if type(v) is not list:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return v
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return tuple(v)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def dictify(mf, excludes):
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen # Transform list of actions into a dictionary keyed by
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen # action key attribute, key attribute and mediator, or
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen # id if there is no key attribute.
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen for a in mf.gen_actions(excludes):
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (a.name == "link" or
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen a.name == "hardlink") and \
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen a.attrs.get("mediator"):
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen akey = (a.name, tuple([
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen a.attrs[a.key_attr],
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen a.attrs.get("mediator-version"),
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen a.attrs.get("mediator-implementation")
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ]))
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen else:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen akey = (a.name, hashify(a.attrs.get(
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen a.key_attr, id(a))))
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen yield (akey, a)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sdict = dict(dictify(self, self_exclude))
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen odict = dict(dictify(origin, origin_exclude))
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sset = set(sdict.iterkeys())
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen oset = set(odict.iterkeys())
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen added = [(None, sdict[i]) for i in sset - oset]
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen removed = [(odict[i], None) for i in oset - sset]
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen changed = [
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen (odict[i], sdict[i])
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen for i in oset & sset
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if odict[i].different(sdict[i])
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen ]
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen # XXX Do changed actions need to be sorted at all? This is
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # likely to be the largest list, so we might save significant
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # time by not sorting. Should we sort above? Insert into a
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # sorted list?
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # singlesort = lambda x: x[0] or x[1]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen addsort = itemgetter(1)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen remsort = itemgetter(0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen removed.sort(key=remsort, reverse=True)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen added.sort(key=addsort)
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen changed.sort(key=addsort)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen return ManifestDifference(added, changed, removed)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen @staticmethod
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def comm(compare_m):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Like the unix utility comm, except that this function
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen takes an arbitrary number of manifests and compares them,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen returning a tuple consisting of each manifest's actions
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen that are not the same for all manifests, followed by a
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen list of actions that are the same in each manifest."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # Must specify at least one manifest.
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen assert compare_m
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen dups = []
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # construct list of dictionaries of actions in each
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen # manifest, indexed by unique key and variant combination
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen m_dicts = []
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen for m in compare_m:
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen m_dict = {}
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen for a in m.gen_actions():
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen # The unique key for each action is based on its
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen # type, key attribute, and unique variants set
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen # on the action.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen try:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen key = set(a.attrlist(a.key_attr))
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen key.update(
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "%s=%s" % (v, a.attrs[v])
484efa22e65c509f787dbbc892351146c726c257Timo Sirainen for v in a.get_varcet_keys()[0]
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen )
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen key = tuple(key)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except KeyError:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # If there is no key attribute for the
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # action, then fallback to the object
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen # id for the action as its identifier.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen key = (id(a),)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen # catch duplicate actions here...
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if m_dict.setdefault((a.name, key), a) != a:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen dups.append((m_dict[(a.name, key)], a))
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen m_dicts.append(m_dict)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if dups:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen raise ManifestError(duplicates=dups)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen # construct list of key sets in each dict
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen m_sets = [
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen set(m.keys())
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen for m in m_dicts
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen common_keys = reduce(lambda a, b: a & b, m_sets)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen # determine which common_keys have common actions
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for k in common_keys.copy():
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for i in range(len(m_dicts) - 1):
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if m_dicts[i][k].different(
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen m_dicts[i + 1][k]):
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen common_keys.remove(k)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return tuple(
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen [
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainen [m_dicts[i][k] for k in m_sets[i] - common_keys]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen for i in range(len(m_dicts))
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen +
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen [
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen [ m_dicts[0][k] for k in common_keys ]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen )
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen def combined_difference(self, origin, ov=EmptyI, sv=EmptyI):
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen """Where difference() returns three lists, combined_difference()
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen returns a single list of the concatenation of the three."""
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return list(chain(*self.difference(origin, ov, sv)))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def humanized_differences(self, other, ov=EmptyI, sv=EmptyI):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Output expects that self is newer than other. Use of sets
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen requires that we convert the action objects into some marshalled
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen form, otherwise set member identities are derived from the
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen object pointers, rather than the contents."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen l = self.difference(other, ov, sv)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen out = ""
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for src, dest in chain(*l):
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if not src:
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen out += "+ %s\n" % str(dest)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen elif not dest:
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen out += "- %s\n" + str(src)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else:
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen out += "%s -> %s\n" % (src, dest)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return out
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen def _gen_dirs_to_str(self):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Generate contents of dircache file containing all dirctories
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen referenced explicitly or implicitly from self.actions. Include
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen variants as values; collapse variants where possible."""
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen def gen_references(a):
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for d in expanddirs(a.directory_references()):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield d
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen dirs = self._actions_to_dict(gen_references)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for d in dirs:
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen for v in dirs[d]:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield "dir path=%s %s\n" % \
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (d, " ".join("%s=%s" % t \
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen for t in v.iteritems()))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def _gen_mediators_to_str(self):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Generate contents of mediatorcache file containing all
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mediators referenced explicitly or implicitly from self.actions.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen Include variants as values; collapse variants where possible."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def gen_references(a):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (a.name == "link" or a.name == "hardlink") and \
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen "mediator" in a.attrs:
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen yield (a.attrs.get("mediator"),
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen a.attrs.get("mediator-priority"),
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen a.attrs.get("mediator-version"),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen a.attrs.get("mediator-implementation"))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mediators = self._actions_to_dict(gen_references)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen for mediation, mvariants in mediators.iteritems():
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen values = {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "mediator-priority": mediation[1],
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "mediator-version": mediation[2],
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen "mediator-implementation": mediation[3],
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen for mvariant in mvariants:
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen a = "set name=pkg.mediator " \
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen "value=%s %s %s\n" % (mediation[0],
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen " ".join((
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen "=".join(t)
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen for t in values.iteritems()
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen if t[1]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen )),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen " ".join((
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "=".join(t)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for t in mvariant.iteritems()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen )
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield a
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen def _actions_to_dict(self, references):
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen """create dictionary of all actions referenced explicitly or
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen implicitly from self.actions... include variants as values;
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen collapse variants where possible"""
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen refs = {}
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # build a dictionary containing all directories tagged w/
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # variants
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen for a in self.actions:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen v, f = a.get_varcet_keys()
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen variants = dict((name, a.attrs[name]) for name in v + f)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen for ref in references(a):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if ref not in refs:
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen refs[ref] = [variants]
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen elif variants not in refs[ref]:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen refs[ref].append(variants)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # remove any tags if any entries are always delivered (NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for ref in refs:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if {} in refs[ref]:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen refs[ref] = [{}]
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen continue
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # could collapse refs where all variants are present
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # (the current logic only collapses them if at least
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # one reference is delivered without a facet or
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen # variant)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return refs
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen def get_directories(self, excludes):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen """ return a list of directories implicitly or
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen explicitly referenced by this object"""
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if self.excludes == excludes:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen excludes = EmptyI
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen assert excludes == EmptyI or self.excludes == EmptyI
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen try:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen alist = self._cache["manifest.dircache"]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except KeyError:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # generate actions that contain directories
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen alist = self._cache["manifest.dircache"] = [
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen actions.fromstr(s.rstrip())
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen for s in self._gen_dirs_to_str()
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen ]
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen s = set([
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen a.attrs["path"]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for a in alist
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if not excludes or a.include_this(excludes)
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen ])
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen return list(s)
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen def gen_mediators(self, excludes=EmptyI):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """A generator function that yields tuples of the form (mediator,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mediations) expressing the set of possible mediations for this
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen package, where 'mediations' is a set() of possible mediations for
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen the mediator. Each mediation is a tuple of the form (priority,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen version, implementation).
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if self.excludes == excludes:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen excludes = EmptyI
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen assert excludes == EmptyI or self.excludes == EmptyI
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen try:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen alist = self._cache["manifest.mediatorcache"]
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen except KeyError:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen # generate actions that contain mediators
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen alist = self._cache["manifest.mediatorcache"] = [
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen actions.fromstr(s.rstrip())
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for s in self._gen_mediators_to_str()
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen ]
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen ret = defaultdict(set)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for attrs in (
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen act.attrs
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for act in alist
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if not excludes or act.include_this(excludes)):
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen med_ver = attrs.get("mediator-version")
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if med_ver:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen try:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen med_ver = version.Version(med_ver,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen "5.11")
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen except version.VersionError:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen # Consider this mediation unavailable
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen # if it can't be parsed for whatever
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen # reason.
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen continue
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret[attrs["value"]].add((
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen attrs.get("mediator-priority"),
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen med_ver,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen attrs.get("mediator-implementation"),
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ))
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for m in ret:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen yield m, ret[m]
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen def gen_actions(self, excludes=EmptyI):
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen """Generate actions in manifest through ordered callable list"""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if self.excludes == excludes:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen excludes = EmptyI
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen assert excludes == EmptyI or self.excludes == EmptyI
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for a in self.actions:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for c in excludes:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if not c(a):
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen else:
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen yield a
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen def gen_actions_by_type(self, atype, excludes=EmptyI):
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen """Generate actions in the manifest of type "type"
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen through ordered callable list"""
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if self.excludes == excludes:
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen excludes = EmptyI
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen assert excludes == EmptyI or self.excludes == EmptyI
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen for a in self.actions_bytype.get(atype, []):
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen for c in excludes:
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen if not c(a):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen break
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen else:
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen yield a
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen
ff640b54224881abbc21141f217c881d6ba5cd28Timo Sirainen def gen_actions_by_types(self, atypes, excludes=EmptyI):
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen """Generate actions in the manifest of types "atypes"
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen through ordered callable list."""
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen for atype in atypes:
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen for a in self.gen_actions_by_type(atype,
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen excludes=excludes):
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen yield a
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen def gen_key_attribute_value_by_type(self, atype, excludes=EmptyI):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Generate the value of the key attribute for each action
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen of type "type" in the manifest."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return (
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen a.attrs.get(a.key_attr)
1276e0340fe29495b6694dc7508f070cf6fca1cfTimo Sirainen for a in self.gen_actions_by_type(atype, excludes)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen )
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def duplicates(self, excludes=EmptyI):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Find actions in the manifest which are duplicates (i.e.,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen represent the same object) but which are not identical (i.e.,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen have all the same attributes)."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen def fun(a):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Return a key on which actions can be sorted."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return a.name, a.attrs.get(a.key_attr, id(a))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen alldups = []
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen acts = [a for a in self.gen_actions(excludes)]
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for k, g in groupby(sorted(acts, key=fun), fun):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen glist = list(g)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen dups = set()
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen for i in range(len(glist) - 1):
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if glist[i].different(glist[i + 1]):
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen dups.add(glist[i])
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen dups.add(glist[i + 1])
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if dups:
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen alldups.append((k, dups))
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen return alldups
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def __content_to_actions(self, content):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen accumulate = ""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen lineno = 0
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen errors = []
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if isinstance(content, basestring):
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen # Get an iterable for the string.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen content = content.splitlines()
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for l in content:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen lineno += 1
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen l = l.lstrip()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if l.endswith("\\"): # allow continuation chars
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen accumulate += l[0:-1] # elide backslash
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen continue
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen elif accumulate:
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen l = accumulate + l
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen accumulate = ""
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if not l or l[0] == "#": # ignore blank lines & comments
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen continue
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen try:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen yield actions.fromstr(l)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen except actions.ActionError, e:
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen # Accumulate errors and continue so that as
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen # much of the action data as possible can be
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # parsed.
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen e.fmri = self.fmri
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen e.lineno = lineno
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen errors.append(e)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if errors:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen raise apx.InvalidPackageErrors(errors)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def set_content(self, content=None, excludes=EmptyI, pathname=None,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen signatures=False):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Populate the manifest with actions.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'content' is an optional value containing either the text
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen representation of the manifest or an iterable of
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen action objects.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'excludes' is optional. If provided it must be a length two
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen list with the variants to be excluded as the first element and
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen the facets to be excluded as the second element.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'pathname' is an optional filename containing the location of
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen the manifest content.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'signatures' is an optional boolean value that indicates whether
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen a manifest signature should be generated. This is only possible
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen when 'content' is a string or 'pathname' is provided.
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen """
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen assert content is not None or pathname is not None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen assert not (content and pathname)
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen self.actions = []
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen self.actions_bytype = {}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._variants = None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._facets = None
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen self.attributes = {}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._cache = {}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # So we could build up here the type/key_attr dictionaries like
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # sdict and odict in difference() above, and have that be our
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # main datastore, rather than the simple list we have now. If
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # we do that here, we can even assert that the "same" action
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # can't be in a manifest twice. (The problem of having the same
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # action more than once in packages that can be installed
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen # together has to be solved somewhere else, though.)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if pathname:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen try:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen with open(pathname, "rb") as mfile:
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen content = mfile.read()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except EnvironmentError, e:
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen raise apx._convert_error(e)
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if isinstance(content, basestring):
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if signatures:
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen # Generate manifest signature based upon
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen # input content, but only if signatures
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen # were requested.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.signatures = {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen "sha-1": self.hash_create(content)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen content = self.__content_to_actions(content)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen for action in content:
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen self.add_action(action, excludes)
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen self.excludes = excludes
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen # Make sure that either no excludes were provided or that both
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen # variants and facet excludes were.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen assert len(self.excludes) in (0, 2)
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen def exclude_content(self, excludes):
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen """Remove any actions from the manifest which should be
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen excluded."""
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen self.set_content(content=self.actions, excludes=excludes)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen def add_action(self, action, excludes):
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen """Performs any needed transformations on the action then adds
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen it to the manifest.
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen The "action" parameter is the action object that should be
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen added to the manifest.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen The "excludes" parameter is the variants to exclude from the
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen manifest."""
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen attrs = action.attrs
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen aname = action.name
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen # XXX handle legacy transition issues; not needed once support
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen # for upgrading images from older releases (< build 151) has
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen # been removed.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if "opensolaris.zone" in attrs and \
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen "variant.opensolaris.zone" not in attrs:
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen attrs["variant.opensolaris.zone"] = \
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen attrs["opensolaris.zone"]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if aname == "set" and attrs["name"] == "authority":
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen # Translate old action to new.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen attrs["name"] = "publisher"
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if excludes and not action.include_this(excludes):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if self._variants:
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen # Reset facet/variant cache if needed (if one is set,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # then both are set, so only need to check for one).
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._facets = None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._variants = None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.actions.append(action)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.actions_bytype[aname].append(action)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen except KeyError:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.actions_bytype.setdefault(aname, []).append(action)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # add any set actions to attributes
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if aname == "set":
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.fill_attributes(action)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen def fill_attributes(self, action):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """Fill attribute array w/ set action contents."""
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen keyvalue = action.attrs["name"]
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if keyvalue == "fmri":
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen keyvalue = "pkg.fmri"
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if keyvalue not in self.attributes:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.attributes[keyvalue] = \
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen action.attrs["value"]
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen except KeyError: # ignore broken set actions
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen pass
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen @staticmethod
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen def search_dict(file_path, excludes, return_line=False,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen log=None):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """Produces the search dictionary for a specific manifest.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen A dictionary is constructed which maps a tuple of token,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen action type, key, and the value that matched the token to
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen the byte offset into the manifest file. file_path is the
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen path to the manifest file. excludes is the variants which
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen should be allowed in this image. return_line is a debugging
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen flag which makes the function map the information to the
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen string of the line, rather than the byte offset to allow
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen easier debugging."""
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if log is None:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen log = lambda x: None
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen try:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen file_handle = file(file_path, "rb")
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen except EnvironmentError, e:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if e.errno != errno.ENOENT:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen raise
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen log((_("%(fp)s:\n%(e)s") %
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen { "fp": file_path, "e": e }))
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return {}
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen cur_pos = 0
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen line = file_handle.readline()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen action_dict = {}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen def __handle_list(lst, cp):
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen """Translates what actions.generate_indices produces
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen into a dictionary mapping token, action_name, key, and
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen the value that should be displayed for matching that
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen token to byte offsets into the manifest file.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen The "lst" parameter is the data to be converted.
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen The "cp" parameter is the byte offset into the file
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen for the action which produced lst."""
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen for action_name, subtype, tok, full_value in lst:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if action_name == "set":
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if full_value is None:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen full_value = tok
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen else:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if full_value is None:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen full_value = subtype
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if full_value is None:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen full_value = action_name
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if isinstance(tok, list):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen __handle_list([
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen (action_name, subtype, t,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen full_value)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen for t in tok
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen ], cp)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen else:
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen if (tok, action_name, subtype,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen full_value) in action_dict:
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen action_dict[(tok, action_name,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen subtype, full_value)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen ].append(cp)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen else:
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen action_dict[(tok, action_name,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen subtype, full_value)] = [cp]
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen while line:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen l = line.strip()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if l and l[0] != "#":
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen action = actions.fromstr(l)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen except actions.ActionError, e:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen log((_("%(fp)s:\n%(e)s") %
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen { "fp": file_path, "e": e }))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if not excludes or \
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen action.include_this(excludes):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if action.attrs.has_key("path"):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen np = action.attrs["path"].lstrip(os.path.sep)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen action.attrs["path"] = \
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen np
470475238f0472ae2b7a4cca59786ab76eed083cTimo Sirainen try:
974ed9e53724507b99fe02e715e4b6153d2be92bTimo Sirainen inds = action.generate_indices()
3343a61404603b21c246783a7963b77833095f31Timo Sirainen except KeyError, k:
3343a61404603b21c246783a7963b77833095f31Timo Sirainen log(_("%(fp)s contains "
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "an action which is"
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen " missing the "
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen "expected attribute"
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen ": %(at)s.\nThe "
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen "action is:"
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen "%(act)s") %
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen {
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen "fp": file_path,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen "at": k.args[0],
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen "act":l
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen })
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen else:
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen arg = cur_pos
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if return_line:
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen arg = l
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen __handle_list(inds, arg)
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen cur_pos = file_handle.tell()
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen line = file_handle.readline()
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen file_handle.close()
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen return action_dict
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen @staticmethod
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen def hash_create(mfstcontent):
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen """This method takes a string representing the on-disk
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen manifest content, and returns a hash value."""
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sha_1 = hashlib.sha1()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if isinstance(mfstcontent, unicode):
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen # Byte stream expected, so pass encoded.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sha_1.update(mfstcontent.encode("utf-8"))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sha_1.update(mfstcontent)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return sha_1.hexdigest()
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen def validate(self, signatures):
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen """Verifies whether the signatures for the contents of
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen the manifest match the specified signature data. Raises
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen the 'BadManifestSignatures' exception on failure."""
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if signatures != self.signatures:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen raise apx.BadManifestSignatures(self.fmri)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen def store(self, mfst_path):
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen """Store the manifest contents to disk."""
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen t_dir = os.path.dirname(mfst_path)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen t_prefix = os.path.basename(mfst_path) + "."
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen try:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen os.makedirs(t_dir, mode=PKG_DIR_MODE)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen except EnvironmentError, e:
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if e.errno == errno.EACCES:
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen raise apx.PermissionsException(e.filename)
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if e.errno == errno.EROFS:
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen raise apx.ReadOnlyFileSystemException(
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen e.filename)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if e.errno != errno.EEXIST:
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen raise
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen try:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen fd, fn = tempfile.mkstemp(dir=t_dir, prefix=t_prefix)
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen except EnvironmentError, e:
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen if e.errno == errno.EACCES:
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen raise apx.PermissionsException(e.filename)
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen if e.errno == errno.EROFS:
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen raise apx.ReadOnlyFileSystemException(
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen e.filename)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen raise
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mfile = os.fdopen(fd, "wb")
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen #
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen # We specifically avoid sorting manifests before writing
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen # them to disk-- there's really no point in doing so, since
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen # we'll sort actions globally during packaging operations.
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen #
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mfile.write(self.tostr_unsorted())
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mfile.close()
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen try:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen os.chmod(fn, PKG_FILE_MODE)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen portable.rename(fn, mfst_path)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen except EnvironmentError, e:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if e.errno == errno.EACCES:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen raise apx.PermissionsException(e.filename)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if e.errno == errno.EROFS:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen raise apx.ReadOnlyFileSystemException(
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen e.filename)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen raise
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen def get_variants(self, name):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if name not in self.attributes:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return None
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen variants = self.attributes[name]
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if not isinstance(variants, str):
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen return variants
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen return [variants]
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen def get_all_variants(self):
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen """Return a dictionary mapping variant tags to their values."""
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen return variant.VariantCombinationTemplate(dict((
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen (name, self.attributes[name])
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen for name in self.attributes
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if name.startswith("variant.")
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen )))
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen def get(self, key, default):
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen try:
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen return self[key]
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen except KeyError:
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen return default
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen def getbool(self, key, default):
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen """Returns the boolean of the value of the attribute 'key'."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen ret = self.get(key, default).lower()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ret == "true":
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen return True
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen elif ret == "false":
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen return False
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen else:
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen raise ValueError(_("Attribute value '%s' not 'true' or "
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen "'false'" % ret))
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen def get_size(self, excludes=EmptyI):
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen """Returns an integer representing the total size, in bytes, of
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen the Manifest's data payload.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'excludes' is a list of variants which should be allowed when
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen calculating the total.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen size = 0
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for a in self.gen_actions(excludes):
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen size += a.get_size()
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return size
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen def __load_varcets(self):
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen """Private helper function to populate list of facets and
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen variants on-demand."""
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self._facets = {}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self._variants = {}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen for action in self.gen_actions():
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen # append any variants and facets to manifest dict
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen attrs = action.attrs
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen v_list, f_list = action.get_varcet_keys()
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if not (v_list or f_list):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen continue
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen try:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen for v, d in chain(
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen izip(v_list, repeat(self._variants)),
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen izip(f_list, repeat(self._facets))):
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen try:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen d[v].add(attrs[v])
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen except KeyError:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen d[v] = set([attrs[v]])
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen except TypeError:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen # Lists can't be set elements.
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen raise actions.InvalidActionError(action,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen _("%(forv)s '%(v)s' specified multiple times") %
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen {"forv": v.split(".", 1)[0], "v": v})
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen def __get_facets(self):
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if self._facets is None:
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen self.__load_varcets()
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return self._facets
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen def __get_variants(self):
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if self._variants is None:
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen self.__load_varcets()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return self._variants
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen def __getitem__(self, key):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """Return the value for the package attribute 'key'."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return self.attributes[key]
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def __setitem__(self, key, value):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Set the value for the package attribute 'key' to 'value'."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.attributes[key] = value
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen for a in self.actions:
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen if a.name == "set" and a.attrs["name"] == key:
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen a.attrs["value"] = value
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen new_attr = AttributeAction(None, name=key, value=value)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.actions.append(new_attr)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.actions_bytype.setdefault("set", []).append(new_attr)
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen def __contains__(self, key):
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen return key in self.attributes
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen facets = property(lambda self: self.__get_facets())
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen variants = property(lambda self: self.__get_variants())
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainennull = Manifest()
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenclass FactoredManifest(Manifest):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """This class serves as a wrapper for the Manifest class for callers
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen that need efficient access to package data on a per-action type basis.
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen It achieves this by partitioning the manifest into multiple files (one
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen per action type) and then storing an on-disk cache of the directories
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen explictly and implicitly referenced by the manifest each tagged with
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen the appropriate variants/facets."""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def __init__(self, fmri, cache_root, contents=None, excludes=EmptyI,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen pathname=None):
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen """Raises KeyError exception if factored manifest is not present
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen and contents are None; delays reading of manifest until required
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if cache file is present.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen 'fmri' is a PkgFmri object representing the identity of the
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen package.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen 'cache_root' is the pathname of the directory where the manifest
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen and cache files should be stored or loaded from.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen 'contents' is an optional string to use as the contents of the
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen manifest if a cached copy does not already exist.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen 'excludes' is optional. If provided it must be a length two
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen list with the variants to be excluded as the first element and
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen the facets to be exclduded as the second element.
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen 'pathname' is an optional string containing the pathname of a
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen manifest. If not provided, it is assumed that the manifest is
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen stored in a file named 'manifest' in the directory indicated by
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen 'cache_root'. If provided, and contents is also provided, then
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen 'contents' will be stored in 'pathname' if it does not already
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen exist.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen Manifest.__init__(self, fmri)
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen self.__cache_root = cache_root
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen self.__pathname = pathname
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen # Make sure that either no excludes were provided or that both
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen # variants and facet excludes were.
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen assert len(excludes) in (0, 2)
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen self.loaded = False
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen # Do we have a cached copy?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if not os.path.exists(self.pathname):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if contents is None:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen raise KeyError, fmri
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # we have no cached copy; save one
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # don't specify excludes so on-disk copy has
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen # all variants
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.set_content(content=contents)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.__finiload()
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if self.__storeback():
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.__unload()
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen if excludes:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.exclude_content(excludes)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # we have a cached copy of the manifest
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mdpath = self.__cache_path("manifest.dircache")
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # have we computed the dircache?
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if not os.path.exists(mdpath): # we're adding cache
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.excludes = EmptyI # to existing manifest
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen self.__load()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if self.__storeback():
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.__unload()
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if excludes:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.excludes = excludes
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen self.__load()
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen return
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen self.exclude_content(excludes)
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen def __cache_path(self, name):
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return os.path.join(self.__cache_root, name)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen def __load(self):
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen """Load all manifest contents from on-disk copy of manifest"""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.set_content(excludes=self.excludes, pathname=self.pathname)
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen self.__finiload()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def __unload(self):
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen """Unload manifest; used to reduce peak memory comsumption
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen when downloading new manifests"""
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen self.actions = []
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.actions_bytype = {}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self._variants = None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self._facets = None
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen self.attributes = {}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen self.loaded = False
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen def __finiload(self):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """Finish loading.... this part of initialization is common
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen to multiple code paths"""
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen self.loaded = True
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def __storeback(self):
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen """ store the current action set; also create per-type
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen caches. Return True if data was saved, False if not"""
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen assert self.loaded
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.store(self.pathname)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen self.__storebytype()
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return True
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except apx.PermissionsException:
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen # this allows us to try to cache new manifests
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen # when non-root w/o failures.
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return False
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen def __storebytype(self):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """ create manifest.<typename> files to accelerate partial
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen parsing of manifests. Separate from __storeback code to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen allow upgrade to reuse existing on disk manifests"""
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen assert self.loaded
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen t_dir = self.__cache_root
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # Ensure target cache directory and intermediates exist.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen misc.makedirs(t_dir)
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen # create per-action type cache; use rename to avoid
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen # corrupt files if ^C'd in the middle
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen for n in self.actions_bytype.keys():
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen t_prefix = "manifest.%s." % n
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen fd, fn = tempfile.mkstemp(dir=t_dir, prefix=t_prefix)
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen f = os.fdopen(fd, "wb")
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen for a in self.actions_bytype[n]:
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen f.write("%s\n" % a)
325f4573edfa5b751832ac01023f3e81be992bf0Timo Sirainen f.close()
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen os.chmod(fn, PKG_FILE_MODE)
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen portable.rename(fn, self.__cache_path("manifest.%s" % n))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def create_cache(name, refs):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen fd, fn = tempfile.mkstemp(dir=t_dir,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen prefix="manifest.dircache.")
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen with os.fdopen(fd, "wb") as f:
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen f.writelines(refs())
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen os.chmod(fn, PKG_FILE_MODE)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen portable.rename(fn, self.__cache_path(name))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except EnvironmentError, e:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen raise apx._convert_error(e)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen create_cache("manifest.dircache", self._gen_dirs_to_str)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen create_cache("manifest.mediatorcache",
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen self._gen_mediators_to_str)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen @staticmethod
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen def clear_cache(cache_root):
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen """Remove all manifest cache files found in the given directory
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (excluding the manifest itself).
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen try:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen for cname in os.listdir(cache_root):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if not cname.startswith("manifest."):
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen continue
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen try:
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen portable.remove(os.path.join(
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen cache_root, cname))
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen except EnvironmentError, e:
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen if e.errno != errno.ENOENT:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen raise
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen except EnvironmentError, e:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if e.errno != errno.ENOENT:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # Only raise error if failure wasn't due to
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # cache directory not existing.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen raise apx._convert_error(e)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen def __load_cached_data(self, name):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen """Private helper function for loading arbitrary cached manifest
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen data.
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen """
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mpath = self.__cache_path(name)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if not os.path.exists(mpath):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # no cached copy
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if not self.loaded:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # need to load from disk
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.__load()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen assert self.loaded
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen # we have cached copy on disk; use it
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen try:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen with open(mpath, "rb") as f:
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen self._cache[name] = [
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen a for a in
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen (
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen actions.fromstr(s.rstrip())
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for s in f
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen )
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if not self.excludes or
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen a.include_this(self.excludes)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ]
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen except EnvironmentError, e:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen raise apx._convert_error(e)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen def get_directories(self, excludes):
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen """ return a list of directories implicitly or explicitly
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen referenced by this object
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen """
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen self.__load_cached_data("manifest.dircache")
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return Manifest.get_directories(self, excludes)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen def gen_actions_by_type(self, atype, excludes=EmptyI):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """ generate actions of the specified type;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen use already in-memory stuff if already loaded,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen otherwise use per-action types files"""
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if self.loaded: #if already loaded, use in-memory cached version
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # invoke subclass method to generate action by action
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen for a in Manifest.gen_actions_by_type(self, atype,
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen excludes):
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen yield a
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # This checks if we've already written out the factored
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # manifest files. If so, we'll use it, and if not, then
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # we'll load the full manifest.
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mpath = self.__cache_path("manifest.dircache")
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if not os.path.exists(mpath):
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # no cached copy :-(
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if not self.loaded:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # get manifest from disk
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.__load()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen # invoke subclass method to generate action by action
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen for a in Manifest.gen_actions_by_type(self, atype,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen excludes):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen yield a
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen else:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if excludes == EmptyI:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen excludes = self.excludes
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen assert excludes == self.excludes or \
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.excludes == EmptyI
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen # we have a cached copy - use it
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mpath = self.__cache_path("manifest.%s" % atype)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if not os.path.exists(mpath):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return # no such action in this manifest
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen with open(mpath, "rb") as f:
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen for l in f:
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen a = actions.fromstr(l.rstrip())
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if not excludes or \
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen a.include_this(excludes):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen yield a
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen def gen_mediators(self, excludes):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen """A generator function that yields set actions expressing the
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen set of possible mediations for this package.
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen """
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen self.__load_cached_data("manifest.mediatorcache")
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return Manifest.gen_mediators(self, excludes)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen def __load_attributes(self):
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen """Load attributes dictionary from cached set actions;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen this speeds up pkg info a lot"""
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen mpath = self.__cache_path("manifest.set")
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if not os.path.exists(mpath):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return False
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen with open(mpath, "rb") as f:
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen for l in f:
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen a = actions.fromstr(l.rstrip())
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if not self.excludes or \
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen a.include_this(self.excludes):
6597506f9317f3be644e708c9153dacaeeece84cTimo Sirainen self.fill_attributes(a)
6597506f9317f3be644e708c9153dacaeeece84cTimo Sirainen return True
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen def __getitem__(self, key):
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen if not self.loaded and not self.__load_attributes():
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.__load()
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return Manifest.__getitem__(self, key)
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen def __setitem__(self, key, value):
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen """No assignments to factored manifests allowed."""
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen assert "FactoredManifests are not dicts"
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen def __contains__(self, key):
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if not self.loaded and not self.__load_attributes():
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen self.__load()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return Manifest.__contains__(self, key)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen def get(self, key, default):
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen try:
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return self[key]
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen except KeyError:
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return default
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def get_variants(self, name):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if not self.loaded and not self.__load_attributes():
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen self.__load()
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return Manifest.get_variants(self, name)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def get_all_variants(self):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if not self.loaded and not self.__load_attributes():
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen self.__load()
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return Manifest.get_all_variants(self)
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen @staticmethod
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen def search_dict(cache_path, excludes, return_line=False):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return Manifest.search_dict(cache_path, excludes,
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return_line=return_line)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def gen_actions(self, excludes=EmptyI):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if not self.loaded:
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen self.__load()
f755bf320bfa321de210b85d6455eb6d7092bb4aTimo Sirainen return Manifest.gen_actions(self, excludes=excludes)
f755bf320bfa321de210b85d6455eb6d7092bb4aTimo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def __str__(self, excludes=EmptyI):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if not self.loaded:
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen self.__load()
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return Manifest.__str__(self)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen def duplicates(self, excludes=EmptyI):
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if not self.loaded:
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen self.__load()
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return Manifest.duplicates(self, excludes=excludes)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen def difference(self, origin, origin_exclude=EmptyI,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen self_exclude=EmptyI):
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen if not self.loaded:
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen self.__load()
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return Manifest.difference(self, origin,
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen origin_exclude=origin_exclude,
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen self_exclude=self_exclude)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen @property
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen def pathname(self):
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen """The absolute pathname of the file containing the manifest."""
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen if self.__pathname:
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return self.__pathname
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return os.path.join(self.__cache_root, "manifest")
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainenclass EmptyFactoredManifest(Manifest):
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen """Special class for pkgplan's need for a empty manifest;
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen the regular null manifest doesn't support get_directories
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen and making the factored manifest code handle this case is
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen too ugly..."""
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen def __init__(self):
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen Manifest.__init__(self)
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def difference(self, origin, origin_exclude=EmptyI,
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen self_exclude=EmptyI):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen """Return three lists of action pairs representing origin and
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen destination actions. The first list contains the pairs
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen representing additions, the second list contains the pairs
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen representing updates, and the third list contains the pairs
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen representing removals. All three lists are in the order in
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen which they should be executed."""
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen # The difference for this case is simply everything in the
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen # origin has been removed. This is an optimization for
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen # uninstall.
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return ManifestDifference([], [],
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen [(a, None) for a in origin.gen_actions(origin_exclude)])
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen @staticmethod
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen def get_directories(excludes):
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen return []
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen def exclude_content(self, *args, **kwargs):
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen # This method is overridden so that self.excludes is never set
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen # on the singleton NullFactoredManifest.
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen return
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen def set_content(self, *args, **kwargs):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen raise RuntimeError("Cannot call set_content on an "
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "EmptyFactoredManifest")
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo SirainenNullFactoredManifest = EmptyFactoredManifest()
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenclass ManifestError(Exception):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen """Simple Exception class to handle manifest specific errors"""
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen def __init__(self, duplicates=EmptyI):
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen self.__duplicates = duplicates
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen def __str__(self):
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen ret = []
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen for d in self.__duplicates:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen ret.append("%s\n%s\n\n" % d)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen return "\n".join(ret)
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen