23254680 'false' should be assumed for unknown variants s12b100
authorYiteng Zhang <yiteng.zhang@oracle.com>
Mon, 23 May 2016 16:36:00 -0700
changeset 3363 a4443a665461
parent 3362 efff5c56c368
child 3364 928d047c9a9a
23254680 'false' should be assumed for unknown variants
doc/dev-guide/chpt7.txt
doc/facets.txt
src/client.py
src/man/pkg.7
src/modules/_varcet.c
src/modules/client/api.py
src/modules/variant.py
src/tests/cli/t_change_variant.py
src/tests/cli/t_pkg_varcet.py
src/tests/cli/t_variants.py
--- a/doc/dev-guide/chpt7.txt	Wed May 18 13:58:02 2016 -0700
+++ b/doc/dev-guide/chpt7.txt	Mon May 23 16:36:00 2016 -0700
@@ -92,18 +92,18 @@
 builds and merge them together.  This is far more reliable and faster 
 than attempting to construct such packages manually.
 
-In general, it is not practical to define new variants without
-modifying the packaging system as no practical means currently exists
-for defining a default value for variants in general.  Package developers
-cannot define new variants at present.
+The ``variant.debug.*`` portion of the variant namespace is explicitly
+predefined to have a default version of ``false``; thus, developers
+can provide debug versions of their components, tagged with the
+appropriate variant, and users can select that variant if problems
+arise.  Remember that variants are set per image, so selecting a
+suitable name that is unique at the appropriate resolution for that
+piece of software is important.
 
-However, the ``variant.debug.*`` portion of the variant namespace is predefined
-to have a default version of ``false``; thus, developers can provide debug
-versions of their components, tagged with the appropriate variant, and
-users can select that variant if problems arise.  Remember that
-variants are set per image, so selecting a suitable name that
-is unique at the appropriate resolution for that piece of software 
-is important.
+In addition, any variant tags not described here are assumed to
+have a default value of ``false`` in the image.  This allows
+the definition of custom variants not explicitly set in the
+image for use in packages.
 
 Note that variant tags are applied to any actions that differ between
 architectures during merging; this includes dependencies, ``set`` actions,
--- a/doc/facets.txt	Wed May 18 13:58:02 2016 -0700
+++ b/doc/facets.txt	Mon May 23 16:36:00 2016 -0700
@@ -122,4 +122,4 @@
 variant.arch		 one of sparc, i386 as set by platform code
 variant.opensolaris.zone either global or nonglobal as set by image type
 variant.debug.<all>	 false
-
+variant.<unknown>	 false	all unknown variants default to 'false'
--- a/src/client.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/client.py	Mon May 23 16:36:00 2016 -0700
@@ -1970,6 +1970,10 @@
                 if not name.startswith("variant."):
                         name = "variant.{0}".format(name)
 
+                # forcibly lower-case for 'true' or 'false'
+                if not value.islower() and value.lower() in ("true", "false"):
+                        value = value.lower()
+
                 # make sure the user didn't specify duplicate variants
                 if name in variants:
                         usage(_("{subcmd}: duplicate variant specified: "
--- a/src/man/pkg.7	Wed May 18 13:58:02 2016 -0700
+++ b/src/man/pkg.7	Mon May 23 16:36:00 2016 -0700
@@ -1172,7 +1172,7 @@
 whatever architectures the distribution
 supports. (Only <literal>i386</literal> and <literal>sparc</literal> are used
 in Oracle Solaris.) The exception are the <literal>debug</literal> variants.
-The <literal>debug</literal> variants can only be set to <literal>true</literal>
+The <literal>debug</literal> variants should only be set to <literal>true</literal>
 or <literal>false</literal>; other values have undefined behavior. If a file
 action has both non-debug and debug versions, both versions must have the
 applicable <literal>debug</literal> variant explicitly set, as shown in the
@@ -1185,10 +1185,10 @@
   path=etc/motd pkg.csize=68 pkg.size=48 preserve=true &bsol;
   variant.debug.osnet=false</programlisting>
 <para>The variant value must be set on the image in order for a package using
-the variant to be installed. The <literal>arch</literal> and
-<literal>zone</literal> variants are set by the program that creates the image
-and installs its initial contents. The <literal>debug.*</literal> variants are
-<literal>false</literal> in the image by default.</para>
+the variant to be installed; by default all unspecified variants have the value
+'false', which may or may not make the package installable. The
+<literal>arch</literal> and <literal>zone</literal> variants are set by the
+program that creates the image and installs its initial contents.</para>
 <itemizedlist>
 <para>The facets and variants set on the image affect whether a particular
 action is installed.</para>
@@ -1215,8 +1215,7 @@
 both the facets and the variants allow the action to be installed.</para>
 </listitem>
 </itemizedlist>
-<para>You can create custom facet tags and <literal>variant.debug.*</literal>
-variant tags. See
+<para>You can create custom facet tags and variant tags. See
 <citetitle>Packaging and Delivering Software With the Image Packaging System in Oracle Solaris 11.2</citetitle>
 for more information. The following tags are in common use in Oracle
 Solaris.</para>
--- a/src/modules/_varcet.c	Wed May 18 13:58:02 2016 -0700
+++ b/src/modules/_varcet.c	Mon May 23 16:36:00 2016 -0700
@@ -209,10 +209,9 @@
 			if (sysv == NULL) {
 				/*
 				 * If system variant value doesn't exist, then
-				 * allow the action if it is a debug variant
-				 * that is "false".
+				 * allow the action if it is a variant that is "false".
 				 */
-				if ((strncmp(as, "variant.debug.", 14) == 0) &&
+				if ((strncmp(as, "variant.", 8) == 0) &&
 				    (strncmp(av, "false", 5) != 0)) {
 					Py_DECREF(act_attrs);
 					Py_RETURN_FALSE;
--- a/src/modules/client/api.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/modules/client/api.py	Mon May 23 16:36:00 2016 -0700
@@ -1049,12 +1049,6 @@
                             for p in patterns
                             if "*" not in p and "?" not in p
                         )
-                        # Only debug variants can have an implicit value.
-                        iset = set(
-                            p
-                            for p in iset
-                            if p.startswith("variant.debug.")
-                        )
                 vlist = sorted(vimg | set(vpkg.keys()) | iset)
 
                 # Generate the results.
--- a/src/modules/variant.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/modules/variant.py	Mon May 23 16:36:00 2016 -0700
@@ -110,10 +110,8 @@
                 if item in self:
                         return item, dict.__getitem__(self, item)
 
-                # The trailing '.' is to encourage namespace usage.
-                if item.startswith("variant.debug."):
-                        return None, "false" # 'false' by default
-                raise KeyError("unknown variant {0}".format(item))
+                # Unknown variants have a default implicit value 'false'.
+                return None, "false"
 
         def __getitem__(self, item):
                 return self.__getitem_internal(item)[1]
--- a/src/tests/cli/t_change_variant.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/tests/cli/t_change_variant.py	Mon May 23 16:36:00 2016 -0700
@@ -82,7 +82,18 @@
         add set name=variant.unknown value=bar value=foo
         add file tmp/bar path=usr/bin/foobar mode=0755 owner=root group=root variant.unknown=bar
         add file tmp/foo path=usr/bin/foobar mode=0755 owner=root group=root variant.unknown=foo
-        close """
+        close
+        open [email protected]
+        add set name=variant.unknown value=true value=false
+        add file tmp/bar path=usr/bin/bar mode=0755 owner=root group=root variant.unknown=false
+        add file tmp/foo path=usr/bin/foo mode=0755 owner=root group=root variant.unknown=true
+        close
+        open [email protected]
+        add set name=variant.unknown value=true value=false
+        add file tmp/bar path=usr/bin/foobar mode=0755 owner=root group=root variant.unknown=false
+        add file tmp/foo path=usr/bin/foobar mode=0755 owner=root group=root variant.unknown=true
+        close
+        """
 
         # this package intentionally has no variant.arch specification.
         pkg_inc = """
@@ -468,36 +479,64 @@
 
                 self.image_create(self.rurl)
 
-                # Install package with unknown variant and verify both files are
-                # present.
+                # First test if unknown variant doesn't have the values of
+                # true/false.
+
+                # Install package with unknown variant and verify both files
+                # are elided.
                 self.pkg("install -v [email protected]")
                 for fname in ("bar", "foo"):
-                        self.f_verify("usr/bin/{0}".format(fname), fname)
+                        self.f_verify("usr/bin/{0}".format(fname), fname,
+                            negate=True)
 
                 # Next, verify upgrade to version of package with unknown
-                # variant fails if new version delivers conflicting content and
-                # variant has not been set.
-                self.pkg("update -vvv [email protected]", exit=1)
+                # variant won't fail if new version delivers conflicting content
+                # and variant has not been set.
+                self.pkg("update -vvv [email protected]")
+                # And the file is still elided.
+                for fname in ("bar", "foo"):
+                        self.f_verify("usr/bin/foobar", fname, negate=True)
 
                 # Next, set unknown variant explicitly and verify content
                 # changes as expected.
                 self.pkg("change-variant unknown=foo")
+                # Verify that foo variant of foobar is now installed.
+                self.f_verify("usr/bin/foobar", "foo")
+                self.f_verify("usr/bin/foobar", "bar", negate=True)
 
-                # Verify bar no longer exists...
-                self.f_verify("usr/bin/bar", "bar", negate=True)
-                # ...and foo still does.
-                self.f_verify("usr/bin/foo", "foo")
+                self.image_destroy()
+                self.image_create(self.rurl)
+
+                # Now test if unknown variant has the values of true/false.
+
+                # Install package with unknown variant and verify that false
+                # variant of content is installed since unknown variants have a
+                # default value of 'false'.
+                self.pkg("install -vvv [email protected]")
+                self.f_verify("usr/bin/bar", "bar")
+                self.f_verify("usr/bin/foo", "foo", negate=True)
 
-                # Next, upgrade to version of package with conflicting content
-                # and verify content changes as expected.
-                self.pkg("update -vvv [email protected]")
+                # Next, verify upgrade to version of package with unknown
+                # variant won't fail if new version delivers conflicting content
+                # and variant has not been set.
+                self.pkg("update -vvv [email protected]")
+                # And that false variant of content is installed.
+                self.f_verify("usr/bin/foobar", "bar")
+                self.f_verify("usr/bin/foobar", "foo", negate=True)
 
-                # Verify bar and foo no longer exist...
-                for fname in ("bar", "foo"):
-                        self.f_verify("usr/bin/{0}".format(fname), fname, negate=True)
-
-                # ...and that foo variant of foobar is now installed.
+                # Next, set unknown variant explicitly and verify content
+                # changes as expected. First test with uppercase 'True'.
+                self.pkg("change-variant unknown=True")
+                # Verify that true variant of foobar is now installed.
                 self.f_verify("usr/bin/foobar", "foo")
+                self.f_verify("usr/bin/foobar", "bar", negate=True)
+                # Now test with lowercase 'true'. Need to set the variant to
+                # some other value first, otherwise it shows nothing to do.
+                self.pkg("change-variant unknown=false")
+                self.pkg("change-variant unknown=true")
+                # Verify that true variant of foobar is now installed.
+                self.f_verify("usr/bin/foobar", "foo")
+                self.f_verify("usr/bin/foobar", "bar", negate=True)
 
         def test_cv_parsable(self):
                 """Test the parsable output of change-variant."""
--- a/src/tests/cli/t_pkg_varcet.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/tests/cli/t_pkg_varcet.py	Mon May 23 16:36:00 2016 -0700
@@ -377,7 +377,14 @@
 """.format(variants)
                 self.__assert_variant_matches(exp_def, names=["debug.foo"])
 
-                # Unmatched because variant is not explicitly set.
+                # Matched because unknown variant is implicitly false.
+                exp_def = """\
+foobar false
+"""
+                self.__assert_variant_matches(exp_def, names=["foobar"])
+
+                # Unmatched because variant is not explicitly set (wildcard
+                # matching looks for explicit variants).
                 self.__assert_variant_fails("'*foo'")
 
                 # Matched case for explicitly set.
@@ -521,15 +528,6 @@
                         self.__assert_variant_matches(exp_def, opts=opts,
                             su_wrap=True)
 
-                        # Unmatched case.
-                        self.__assert_variant_matches_default("", opts=opts,
-                            names=("bogus",), exit=1)
-
-                        # Unmatched case tsv; subtly different as no error
-                        # output is expected.
-                        self.__assert_variant_matches_tsv("", opts=opts,
-                            names=("bogus",), exit=1, errout=False)
-
                 # No output expected for with no variants set and no packages
                 # installed for -v, -av, -i, and -iv.
                 for opts in (("-v",), ("-av",), ("-i",), ("-iv",)):
@@ -600,13 +598,13 @@
 arch {0[variant.arch]}
 icecream strawberry
 opensolaris.zone global
-unknown 
+unknown false
 """.format(variants)
                 self.__assert_variant_matches(exp_def, opts=("-a",))
 
                 # Verify -i output.
                 exp_def = """\
-unknown 
+unknown false
 """.format(variants)
                 self.__assert_variant_matches(exp_def, opts=("-i",))
 
--- a/src/tests/cli/t_variants.py	Wed May 18 13:58:02 2016 -0700
+++ b/src/tests/cli/t_variants.py	Mon May 23 16:36:00 2016 -0700
@@ -172,9 +172,10 @@
                     additional_args="--variant variant.arch={0}".format("sparc"))
                 self.pkg("install silver", exit=1)
 
-                # Verify that debug variants are implicitly false and shown in
+                # Verify that unknown variants are implicitly false and shown in
                 # output of 'pkg variant' before any variants are set.
-                self.pkg("variant -H -F tsv debug", exit=1) # only 'debug.'
+                self.pkg("variant -H -F tsv unknown")
+                self.assertEqual("variant.unknown\tfalse\n", self.output)
                 self.pkg("variant -H -F tsv debug.kernel")
                 self.assertEqual("variant.debug.kernel\tfalse\n", self.output)