def __init__(self, imgroot): self.__imgroot = imgroot self.publishers = {} self.properties = dict( ((p, str(v)) for p, v in default_policies.iteritems())) self.preferred_publisher = None self.filters = {} self.variants = variant.Variants() self.children = []
def __init__(self, imgroot, pubdir): self.__imgroot = imgroot self.__pubdir = pubdir self.__publishers = {} self.__publisher_search_order = [] self.properties = dict(( (p, str(v)) for p, v in default_policies.iteritems() )) self.facets = facet.Facets() self.variants = variant.Variants() self.children = []
def test_cached_gen_actions_by_type(self): """Test that when a factored manifest generates actions by type from its cached source, it takes the excluded content into account.""" contents = """\ set name=pkg.fmri value=pkg:/bar@1 set name=variant.foo value=one value=two dir path=one group=sys owner=root variant.foo=one dir path=two group=sys owner=root variant.foo=two """ m1 = manifest.FactoredManifest("bar@1", self.cache_dir, contents=contents) self.assertEqual(len(list(m1.gen_actions_by_type("dir"))), 2) v = variant.Variants({"variant.foo":"one"}) m1.exclude_content([v.allow_action, lambda x, publisher: True]) self.assertEqual(len(list(m1.gen_actions_by_type("dir"))), 1)
def main_func(): gettext.install("pkg", "/usr/share/locale", codeset=locale.getpreferredencoding()) ignoreattrs = [] onlyattrs = [] onlytypes = [] varattrs = defaultdict(set) try: opts, pargs = getopt.getopt(sys.argv[1:], "i:o:t:v:?", ["help"]) for opt, arg in opts: if opt == "-i": ignoreattrs.append(arg) elif opt == "-o": onlyattrs.append(arg) elif opt == "-t": onlytypes.extend(arg.split(",")) elif opt == "-v": args = arg.split("=") if len(args) != 2: usage(_("variant option incorrect {0}").format(arg)) if not args[0].startswith("variant."): args[0] = "variant." + args[0] varattrs[args[0]].add(args[1]) elif opt in ("--help", "-?"): usage(exitcode=0) except getopt.GetoptError as e: usage(_("illegal global option -- {0}").format(e.opt)) if len(pargs) != 2: usage(_("two manifest arguments are required")) if (pargs[0] == "-" and pargs[1] == "-"): usage(_("only one manifest argument can be stdin")) if ignoreattrs and onlyattrs: usage(_("-i and -o options may not be used at the same time.")) for v in varattrs: if len(varattrs[v]) > 1: usage(_("For any variant, only one value may be " "specified.")) varattrs[v] = varattrs[v].pop() ignoreattrs = set(ignoreattrs) onlyattrs = set(onlyattrs) onlytypes = set(onlytypes) utypes = set(t for t in onlytypes if t == "generic" or t not in pkg.actions.types) if utypes: usage( _("unknown action types: {0}".format(apx.list_to_lang( list(utypes))))) manifest1 = manifest.Manifest() manifest2 = manifest.Manifest() try: # This assumes that both pargs are not '-'. for p, m in zip(pargs, (manifest1, manifest2)): if p == "-": m.set_content(content=sys.stdin.read()) else: m.set_content(pathname=p) except (pkg.actions.ActionError, apx.InvalidPackageErrors) as e: error(_("Action error in file {p}: {e}").format(**locals())) except (EnvironmentError, apx.ApiException) as e: error(e) # # manifest filtering # # filter action type if onlytypes: for m in (manifest1, manifest2): # Must pass complete list of actions to set_content, not # a generator, to avoid clobbering manifest contents. m.set_content(content=list(m.gen_actions_by_types(onlytypes))) # filter variant v1 = manifest1.get_all_variants() v2 = manifest2.get_all_variants() for vname in varattrs: for _path, v, m in zip(pargs, (v1, v2), (manifest1, manifest2)): if vname not in v: continue filt = varattrs[vname] if filt not in v[vname]: usage( _("Manifest {path} doesn't support " "variant {vname}={filt}".format(**locals()))) # remove the variant tag def rip(a): a.attrs.pop(vname, None) return a m.set_content([ rip(a) for a in m.gen_actions( excludes=[variant.Variants({ vname: filt }).allow_action]) ]) m[vname] = filt if varattrs: # need to rebuild these if we're filtering variants v1 = manifest1.get_all_variants() v2 = manifest2.get_all_variants() # we need to be a little clever about variants, since # we can have multiple actions w/ the same key attributes # in each manifest in that case. First, make sure any variants # of the same name have the same values defined. for k in set(v1.keys()) & set(v2.keys()): if v1[k] != v2[k]: error( _("Manifests support different variants " "{v1} {v2}").format(v1=v1, v2=v2)) # Now, get a list of all possible variant values, including None # across all variants and both manifests v_values = dict() for v in v1: v1[v].add(None) for a in v1[v]: v_values.setdefault(v, set()).add((v, a)) for v in v2: v2[v].add(None) for a in v2[v]: v_values.setdefault(v, set()).add((v, a)) diffs = [] for tup in product(*v_values.values()): # build excludes closure to examine only actions exactly # matching current variant values... this is needed to # avoid confusing manifest difference code w/ multiple # actions w/ same key attribute values or getting dups # in output def allow(a, publisher=None): for k, v in tup: if v is not None: if k not in a.attrs or a.attrs[k] != v: return False elif k in a.attrs: return False return True a, c, r = manifest2.difference(manifest1, [allow], [allow]) diffs += a diffs += c diffs += r # License action still causes spurious diffs... check again for now. real_diffs = [(a, b) for a, b in diffs if a is None or b is None or a.different(b)] if not real_diffs: return 0 # define some ordering functions so that output is easily readable # First, a human version of action comparison that works across # variants and action changes... def compare(a, b): if hasattr(a, "key_attr") and hasattr(b, "key_attr") and \ a.key_attr == b.key_attr: res = cmp(a.attrs[a.key_attr], b.attrs[b.key_attr]) if res: return res # sort by variant res = cmp(sorted(list(a.get_variant_template())), sorted(list(b.get_variant_template()))) if res: return res else: res = cmp(a.ordinality, b.ordinality) if res: return res return cmp(str(a), str(b)) # and something to pull the relevant action out of the old value, new # value tuples def tuple_key(a): if not a[0]: return a[1] return a[0] # sort and.... diffs = sorted(diffs, key=tuple_key, cmp=compare) # handle list attributes def attrval(attrs, k, elide_iter=tuple()): def q(s): if " " in s or s == "": return '"{0}"'.format(s) else: return s v = attrs[k] if isinstance(v, list) or isinstance(v, set): out = " ".join([ "{0}={1}".format(k, q(lmt)) for lmt in sorted(v) if lmt not in elide_iter ]) elif " " in v or v == "": out = k + "=\"" + v + "\"" else: out = k + "=" + v return out # figure out when to print diffs def conditional_print(s, a): if onlyattrs: if not set(a.attrs.keys()) & onlyattrs: return False elif ignoreattrs: if not set(a.attrs.keys()) - ignoreattrs: return False print("{0} {1}".format(s, a)) return True different = False for old, new in diffs: if not new: different |= conditional_print("-", old) elif not old: different |= conditional_print("+", new) else: s = [] if not onlyattrs: if (hasattr(old, "hash") and "hash" not in ignoreattrs): if old.hash != new.hash: s.append(" - {0}".format(old.hash)) s.append(" + {0}".format(new.hash)) attrdiffs = (set(new.differences(old)) - ignoreattrs) attrsames = sorted( list( set(old.attrs.keys() + new.attrs.keys()) - set(new.differences(old)))) else: if hasattr(old, "hash") and "hash" in onlyattrs: if old.hash != new.hash: s.append(" - {0}".format(old.hash)) s.append(" + {0}".format(new.hash)) attrdiffs = (set(new.differences(old)) & onlyattrs) attrsames = sorted( list( set(old.attrs.keys() + new.attrs.keys()) - set(new.differences(old)))) for a in sorted(attrdiffs): if a in old.attrs and a in new.attrs and \ isinstance(old.attrs[a], list) and \ isinstance(new.attrs[a], list): elide_set = (set(old.attrs[a]) & set(new.attrs[a])) else: elide_set = set() if a in old.attrs: diff_str = attrval(old.attrs, a, elide_iter=elide_set) if diff_str: s.append(" - {0}".format(diff_str)) if a in new.attrs: diff_str = attrval(new.attrs, a, elide_iter=elide_set) if diff_str: s.append(" + {0}".format(diff_str)) # print out part of action that is the same if s: different = True print("{0} {1} {2}".format( old.name, attrval(old.attrs, old.key_attr), " ".join( ("{0}".format(attrval(old.attrs, v)) for v in attrsames if v != old.key_attr)))) for l in s: print(l) return int(different)
def test_get_directories(self): """Verifies that get_directories() works as expected.""" v = variant.Variants({"variant.arch": "sparc"}) excludes = [v.allow_action, lambda x, publisher: True] m1 = manifest.FactoredManifest("[email protected]", self.cache_dir, pathname=self.foo_content_p5m) all_expected = [ "opt/dir with spaces in value", "opt", "usr/bin", "opt/dir with whitespaces in value", "usr" ] var_expected = ["opt/dir with spaces in value", "opt"] def do_get_dirs(): actual = m1.get_directories([]) self.assertEqualDiff(sorted(all_expected), sorted(actual)) actual = m1.get_directories(excludes) self.assertEqualDiff(sorted(var_expected), sorted(actual)) # Verify get_directories works for initial load. do_get_dirs() # Now repeat experiment using "cached" FactoredManifest. cfile_path = os.path.join(self.cache_dir, "manifest.dircache") self.assertTrue(os.path.isfile(cfile_path)) m1 = manifest.FactoredManifest("[email protected]", self.cache_dir, pathname=self.foo_content_p5m) do_get_dirs() # Now rewrite the dircache so that it contains actions with # paths that are not properly quoted to simulate older, broken # behaviour and verify that the cache will be removed and that # get_directories() still works as expected. m1 = manifest.FactoredManifest("[email protected]", self.cache_dir, pathname=self.foo_content_p5m) with open(cfile_path, "w") as f: for a in m1.gen_actions_by_type("dir"): f.write("dir path={0} {1}\n".format( a.attrs["path"], " ".join( "{0}={1}".format(attr, a.attrs[attr]) for attr in itertools.chain(*a.get_varcet_keys())))) # Repeat tests again. do_get_dirs() # Verify cache file was removed (presumably because we # detected it was malformed). self.assertTrue(not os.path.exists(cfile_path)) # Repeat tests again, verifying cache file is recreated. m1 = manifest.FactoredManifest("[email protected]", self.cache_dir, pathname=self.foo_content_p5m) do_get_dirs() self.assertTrue(os.path.isfile(cfile_path))